/* StarForth — Steady-State Virtual Machine Runtime Copyright (c) 2023–2025 Robert A. James All rights reserved. This file is part of the StarForth project. Licensed under the StarForth License, Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: https://github.com/star.4th@proton.me/StarForth/LICENSE.txt This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. See the License for the specific language governing permissions and limitations under the License. StarForth — Steady-State Virtual Machine Runtime Copyright (c) 2023–2025 Robert A. James All rights reserved. This file is part of the StarForth project. Licensed under the StarForth License, Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: https://github.com/star.4th@proton.me/StarForth/LICENSE.txt This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. See the License for the specific language governing permissions and limitations under the License. */ /** * bootstrap.c - Kernel VM bootstrap + parity emit * * Gated by STARFORTH_ENABLE_VM to avoid touching stable hosted VM builds. * Initializes the VM using kernel host hooks, collects parity, and prints it. */ #ifdef __STARKERNEL__ #include "vm.h" #include "log.h" #include "block_subsystem.h" #include "starkernel/vm/parity.h" #include "starkernel/vm/bootstrap/sk_vm_bootstrap.h" #include "starkernel/hal/hal.h" #include "starkernel/console.h" #include "starkernel/capsule_birth.h" #include "starkernel/capsule_run.h" #include "starkernel/capsule_vm_physics.h" #include "starkernel/vm/arena.h" /* FABRIC-3.md §XXVIII Stage 1 -- sk_vm_native_stack_alloc() */ #include "vm_internal.h" #include "platform_time.h" #include "test_runner/include/test_runner.h" #include "word_source/include/mama_forth_words.h" #if SK_PARITY_DEBUG extern char __text_start[]; extern char __text_end[]; extern char __rodata_start[]; extern char __rodata_end[]; extern char __data_start[]; extern char __data_end[]; extern char __bss_start[]; extern char __bss_end[]; /** * @brief Print a 64-bit value as "0xNNNNNNNNNNNNNNNN" to the kernel console. * * Used by @c sk_bootstrap_debug_log_xt() when @c SK_PARITY_DEBUG is enabled * to dump raw pointer values during XT validation. Formats directly into a * 19-byte stack buffer; no libc dependency. * * Only compiled when @c SK_PARITY_DEBUG is non-zero. * * @param value 64-bit value to format as uppercase-nibble hex. */ static void sk_bootstrap_debug_print_hex(uint64_t value) { char buf[19]; buf[0] = '0'; buf[1] = 'x'; buf[18] = '\0'; for (int i = 0; i < 16; ++i) { uint8_t nibble = (uint8_t)((value >> ((15 - i) * 4)) & 0xF); buf[i + 2] = (nibble < 10) ? (char)('0' + nibble) : (char)('a' + nibble - 10); } console_puts(buf); } /** * @brief Test whether a 64-bit address is a canonical x86-64 virtual address. * * Checks that bits [63:48] are all 0x0000 (user-space range) or all 0xFFFF * (kernel-space range). A non-canonical address indicates a corrupt function * pointer and triggers a @c sk_hal_panic() in the calling debug log function. * * Only compiled when @c SK_PARITY_DEBUG is non-zero. * * @param addr 64-bit address to test. * @return Non-zero if canonical, 0 if non-canonical. */ static int sk_bootstrap_xt_is_canonical(uint64_t addr) { uint64_t upper = addr >> 48; return (upper == 0x0000ULL) || (upper == 0xFFFFULL); } /** * @brief Return a short string naming the memory region containing @p addr. * * Classifies @p addr into: * - @c "null" — zero address * - @c "text" — within the kernel .text section [@c sk_hal_text_start(), * @c sk_hal_text_end()) * - @c "directmap" — ≥ @c 0xffff800000000000 (kernel direct-map range) * - @c "unknown" — anything else * * Used by @c sk_bootstrap_debug_log_xt() to label XTs for diagnostic output. * Rodata/data/bss are not checked because XTs should only reside in .text. * Uses @c sk_hal_text_start() / @c sk_hal_text_end() to avoid GOT-relative * accesses under @c -fPIC. * * Only compiled when @c SK_PARITY_DEBUG is non-zero. * * @param addr 64-bit address to classify. * @return Static string literal naming the region. */ static const char *sk_bootstrap_region_name(uint64_t addr) { if (addr == 0) return "null"; /* Use HAL getters to avoid GOT indirection issues with -fPIC */ uint64_t text_start = sk_hal_text_start(); uint64_t text_end = sk_hal_text_end(); if (addr >= text_start && addr < text_end) { return "text"; } /* For rodata/data/bss, we rely on the HAL whitelist check instead, * since those symbols also have the same GOT issue. XTs should be * in text section anyway. */ if (addr >= 0xffff800000000000ULL) { return "directmap"; } return "unknown"; } /** * @brief Log a dictionary entry's XT pointer and panic if it is invalid. * * Prints a @c "[SK_BOOTDBG]