Reorganize source tree: kernel/, v3/, v4/ split and board infrastructure
Source tree reorganization: - Move StarForth v3 engine to v3/ (src/, include/, Makefile) - Move kernel to kernel/ (src/, include/, linker/, Makefile) - Create v4/ skeleton for F18-ISA golden model (DECOMPOSITION.md, JUSTIFICATION.md) - Move FABRIC-0..4.md to docs/fabric/ - Move ONTOLOGY.md and ROADMAP.md to docs/ Board infrastructure: - Add boards/ser5/, boards/raspi/, boards/milkv/, boards/zynq7020/ - Each board has board.mk (ISA, CPU flags, boot recipe) and README.md - Root Makefile becomes thin dispatcher: boot_image, all, clean, docs take TARGET - make boot_image TARGET=SER5|RASPI|MILKV builds one GPT/MBR image per board - ZYNQ7020 target exists but stops with clear error (ARMv7 port not built yet) - scripts/mkdiskimage.sh builds disk images for all boards Docs pipeline: - docs/book/ with LaTeX master (main.tex) and Makefile - pandoc converts Markdown to LaTeX at build time - Two Lua filters: table-widths.lua (wide tables wrap), code-breaks.lua (inline code breaks) - make docs builds single PDF (754 pages, 0 missing characters) - make docs TARGET=<board> adds board appendix - build/docs/<book|board>/meta.tex stamps git commit into PDF Bug fixes: - 42 include paths that only worked by accident now use correct relative paths - clang-18 hardcode replaced with configurable CC variable (fixed aarch64 build) - Pi 5: kernel_2712.img linked at 0x80000, .bss zeroed, memory reserved - Doxyfile, .clang-tidy, README.md, Kconfig paths updated Verified: - Hosted v3 build passes 1012 tests, 0 failures - SER5 image boots in QEMU (OVMF), POST passes, K exact (65536 = Q48_ONE) - Milk-V image boots in QEMU (OpenSBI + U-Boot + bootefi), POST passes - make clean TARGET=<board> removes only that board and its ISA objects - make all builds all boards, hosted v3, and docs in one run Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
StarKernel — Unified entropy layer (rng_get_bytes)
|
||||
|
||||
Single entropy entry point for the kernel; see include/starkernel/rng.h for
|
||||
the contract and the probe-and-refuse-loudly discipline this implements.
|
||||
|
||||
v2.0.0: virtio-rng is the sole active backend (QEMU-only, uniform across all
|
||||
three arches). The backend-selection switch in rng_get_bytes() is the exact
|
||||
seam where the v2.5.0 real per-arch drivers plug in without touching the call
|
||||
path.
|
||||
|
||||
v2.0.1 (G.4, metadata): the real per-arch backends begin to land here, each
|
||||
guarded by its ISA. amd64 RDRAND is first (SER5). Backend probe order matters
|
||||
and honors the release policy: virtio-rng is tried first so the QEMU path
|
||||
stays on virtio-rng unchanged; the real CPU primitive (RDRAND on amd64) is
|
||||
the fallback that only real hardware reaches, because real boards have no
|
||||
virtio-rng device. Each backend prints its identity at rng_init() so a boot
|
||||
log states exactly which source serves entropy.
|
||||
*/
|
||||
|
||||
#ifndef __STARKERNEL__
|
||||
#error "rng.c is kernel-only"
|
||||
#endif
|
||||
|
||||
#include "starkernel/rng.h"
|
||||
#include "starkernel/virtio_rng.h"
|
||||
#include "starkernel/console.h"
|
||||
|
||||
/* Number of entropy backends known to this build. Each maps to one case in
|
||||
* rng_init() and rng_get_bytes(). v2.0.0: virtio-rng. v2.0.1 adds the amd64
|
||||
* RDRAND backend (real-hardware/SER5 path). */
|
||||
enum {
|
||||
RNG_BACKEND_NONE = 0,
|
||||
RNG_BACKEND_VIRTIO, /* virtio-rng (QEMU, all three arches) */
|
||||
#if defined(__x86_64__) || defined(__amd64__)
|
||||
RNG_BACKEND_RDRAND, /* amd64 RDRAND (real hardware, e.g. Beelink SER5) */
|
||||
#endif
|
||||
};
|
||||
|
||||
static int g_rng_backend = RNG_BACKEND_NONE;
|
||||
|
||||
/* --- amd64 RDRAND backend (G.4) ---------------------------------------- */
|
||||
|
||||
#if defined(__x86_64__) || defined(__amd64__)
|
||||
|
||||
/* CPUID.01H:ECX bit 30 = RDRAND supported. */
|
||||
static inline int rdrand_available(void) {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
__asm__ volatile ("cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(1u), "c"(0u));
|
||||
(void)eax; (void)ebx; (void)edx;
|
||||
return (int)((ecx >> 30) & 1u);
|
||||
}
|
||||
|
||||
/* Execute RDRAND; returns 1 on a valid draw (CF=1), 0 otherwise. */
|
||||
static inline int rdrand64(uint64_t *out) {
|
||||
uint8_t ok;
|
||||
__asm__ volatile ("rdrand %0; setc %1"
|
||||
: "=r"(*out), "=qm"(ok)
|
||||
:
|
||||
: "cc");
|
||||
return (int)ok;
|
||||
}
|
||||
|
||||
static int rdrand_fill(uint8_t *buf, size_t n) {
|
||||
size_t filled = 0;
|
||||
uint32_t attempts = 0;
|
||||
const uint32_t MAX_ATTEMPTS = 128u; /* generous: hardware RDRAND is fast */
|
||||
while (filled < n) {
|
||||
uint64_t w;
|
||||
if (!rdrand64(&w)) {
|
||||
if (++attempts > MAX_ATTEMPTS) return RNG_ERR_NO_BACKEND;
|
||||
continue;
|
||||
}
|
||||
/* Emit whole bytes from the low end. The last (partial) draw is
|
||||
* simply discarded — throwing away entropy is always safe. */
|
||||
for (size_t i = 0; i < sizeof(w) && filled < n; i++)
|
||||
buf[filled++] = (uint8_t)(w >> (8 * i));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* amd64 */
|
||||
|
||||
int rng_init(void) {
|
||||
/* Probe backends in priority order; first success wins. virtio-rng is
|
||||
* tried first so the QEMU path stays on virtio-rng unchanged; the real
|
||||
* per-arch primitive is the fallback that only real hardware reaches. */
|
||||
if (virtio_rng_init() == 0) {
|
||||
g_rng_backend = RNG_BACKEND_VIRTIO;
|
||||
console_println("rng: backend = virtio-rng");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) || defined(__amd64__)
|
||||
if (rdrand_available()) {
|
||||
g_rng_backend = RNG_BACKEND_RDRAND;
|
||||
console_println("rng: backend = rdrand");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Refuse loudly: never fall through to a deterministic seed. */
|
||||
g_rng_backend = RNG_BACKEND_NONE;
|
||||
console_println(
|
||||
"rng: WARNING — no entropy backend available; rng_get_bytes() "
|
||||
"will refuse (no deterministic seed fallback)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rng_ready(void) {
|
||||
return g_rng_backend != RNG_BACKEND_NONE;
|
||||
}
|
||||
|
||||
int rng_get_bytes(uint8_t *buf, size_t n) {
|
||||
if (!buf || n == 0) return RNG_ERR_NO_BACKEND;
|
||||
switch (g_rng_backend) {
|
||||
case RNG_BACKEND_VIRTIO:
|
||||
return virtio_rng_get_bytes(buf, n);
|
||||
#if defined(__x86_64__) || defined(__amd64__)
|
||||
case RNG_BACKEND_RDRAND:
|
||||
return rdrand_fill(buf, n);
|
||||
#endif
|
||||
default:
|
||||
/* No backend: refuse loudly, never return a deterministic
|
||||
* throwaway. */
|
||||
return RNG_ERR_NO_BACKEND;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user