summaryrefslogtreecommitdiff
path: root/arch/riscv/config.cc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/riscv/config.cc')
-rw-r--r--arch/riscv/config.cc276
1 files changed, 0 insertions, 276 deletions
diff --git a/arch/riscv/config.cc b/arch/riscv/config.cc
deleted file mode 100644
index a18a825..0000000
--- a/arch/riscv/config.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-/*
- * RISC-V Architecture Configuration — runtime state and KASLR
- *
- * Provides the runtime (post-KASLR) values of the higher-half
- * virtual address bases. kaslr_init() is called once during
- * early boot, before vmm_init(), to randomise the layout and
- * fill the unified KaslrLayout structure.
- *
- * KASLR slide budget:
- * The default Direct Map starts at 0xFFFFFFC0_0000_0000 (VPN[2]=256).
- * The default Vmemmap starts at 0xFFFFFFD0_0000_0000 (VPN[2]=320).
- * A 1GB superpage occupies one VPN[2] slot. We allow a slide of
- * 0..63 slots (0..63 GB) upward, which keeps both regions inside
- * the upper canonical half and avoids colliding with the kernel
- * text region (linked at VPN[2] = 258 + 2 = ~0xFFFFFFC0_8020_0000).
- *
- * In practice, with 128MB RAM the kernel+direct map only touches
- * VPN[2] 258-259, so a slide of up to 63GB is safe.
- */
-
-#include <arch/config.h>
-#include <lume/fdt.h>
-#include <lume/page.h>
-#include <lume/config.h>
-#include <lume/klog.h>
-#include <lume/kprintf.h>
-#include <lume/random.h>
-
-extern "C" char _stext[], _kernel_end[];
-
-namespace arch {
-
-/* Global KASLR Layout Structure*/
-KaslrLayout g_kaslr_layout = {};
-
-/* Runtime bases — updated by kaslr_layout_compute() */
-uint64 g_direct_map_base = kDirectMapBaseDefault;
-uint64 g_vmemmap_base = kVmemmapBaseDefault;
-
-/* VA Range for validation */
-struct VaRange {
- const char* name;
- uint64 start;
- uint64 end; // exclusive
-};
-
-/* ================================================================
- * Utilities
- * ================================================================ */
-static inline uint64 align_down_page(uint64 v)
-{
- return v & ~(kPageSize - 1);
-}
-
-static inline uint64 align_up_page(uint64 v)
-{
- return (v + kPageSize - 1) & ~(kPageSize - 1);
-}
-
-static uint64 checked_add_u64(uint64 a, uint64 b, const char* detail)
-{
- if (a > (~0ULL - b)) {
- kernel_panic("kaslr: address overflow", detail);
- }
- return a + b;
-}
-
-/* Splitmix64: non-plaintext hash derived from seed (used for seed_hash) */
-static uint64 splitmix64(uint64 x)
-{
- x += 0x9e3779b97f4a7c15ULL;
- x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
- x = x ^ (x >> 27);
- return x * 0x94d049bb133111ebULL;
-}
-
-/* SV39 canonical VA check: bits [63:39] must equal sign bit 38. */
-static bool is_sv39_canonical(uint64 va)
-{
- uint64 sign = (va >> 38) & 1ULL;
- uint64 upper = va >> 39;
- return sign ? (upper == ((1ULL << 25) - 1ULL)) : (upper == 0);
-}
-
-static bool is_sv39_kernel_half(uint64 va)
-{
- return is_sv39_canonical(va) && (((va >> 38) & 1ULL) == 1ULL);
-}
-
-static bool ranges_overlap(const VaRange& a, const VaRange& b)
-{
- return (a.start < b.end) && (b.start < a.end);
-}
-
-/* ================================================================
- * KASLR Computation (Phase A: Centralized in single function)
- *
- * This function:
- * 1. Generates or derives random seed
- * 2. Selects 1GB-aligned slot [0..63]
- * 3. Computes seed_hash via splitmix64
- * 4. Fills KaslrLayout structure completely
- * 5. Validates ranges (canonical, overlaps)
- * 6. Logs according to CONFIG_KASLR_LOG_LEVEL
- * ================================================================ */
-static void kaslr_layout_compute()
-{
-#ifdef CONFIG_KASLR
- constexpr uint64 k1GB = 1ULL << 30;
- constexpr uint64 kMaxSlots = 64;
-
- /* 1. Get seed and source */
- uint64 seed = random_early_seed_value();
- RandomSeedSource rsrc = random_early_seed_source();
- KaslrSeedSource source;
- switch (rsrc) {
- case RandomSeedSource::FdtProvided:
- source = KaslrSeedSource::kFdt;
- break;
- case RandomSeedSource::HwRandom:
- source = KaslrSeedSource::kHardware;
- break;
- case RandomSeedSource::CycleFallback:
- case RandomSeedSource::Unknown:
- default:
- source = KaslrSeedSource::kCycle;
- break;
- }
-
- /* 2. Select random slot and compute slide */
- uint64 raw = get_random_u64();
- uint64 slot = raw % kMaxSlots;
- if (slot == 0) {
- slot = 1; /* slot=0 causes direct_map to overlap with kernel image VA */
- }
- uint64 slide = slot * k1GB;
-
- /* 3. Compute non-plaintext hash */
- uint64 seed_hash = splitmix64(seed ^ 0xdeadbeefdeadbeefULL);
-
- /* 4. Compute randomised bases */
- uint64 direct_map_base = kDirectMapBaseDefault + slide;
- uint64 vmemmap_base = kVmemmapBaseDefault + slide;
-
- /* 5. Fill KaslrLayout */
- g_kaslr_layout.seed = seed;
- g_kaslr_layout.seed_hash = seed_hash;
- g_kaslr_layout.source = source;
- g_kaslr_layout.slot = slot;
- g_kaslr_layout.slide_bytes = slide;
- g_kaslr_layout.policy_id = kKaslrPolicyId;
- g_kaslr_layout.direct_map_base = direct_map_base;
- g_kaslr_layout.vmemmap_base = vmemmap_base;
- g_kaslr_layout.canonical_ok = false;
- g_kaslr_layout.overlap_ok = false;
-
- /* Update global runtime bases */
- g_direct_map_base = direct_map_base;
- g_vmemmap_base = vmemmap_base;
-
- /* 6. Self-check: canonical VA validation and overlap detection */
- uint64 mem_base = 0, mem_size = 0;
- fdt_early_get_mem_info(&mem_base, &mem_size);
- if (mem_size == 0) {
- kernel_panic("kaslr_layout_compute: invalid memory from FDT");
- }
-
- /* Construct VA ranges */
- uint64 num_pages = mem_size / kPageSize;
- uint64 page_bytes = num_pages * sizeof(Page);
- uint64 page_span = align_up_page(page_bytes);
-
- VaRange direct_map {
- "direct-map",
- checked_add_u64(g_direct_map_base, mem_base, "direct_map start"),
- checked_add_u64(checked_add_u64(g_direct_map_base, mem_base,
- "direct_map start"),
- mem_size, "direct_map end"),
- };
-
- VaRange vmemmap {
- "vmemmap",
- g_vmemmap_base,
- checked_add_u64(g_vmemmap_base, page_span, "vmemmap end"),
- };
-
- VaRange kernel_img {
- "kernel-image",
- align_down_page(reinterpret_cast<uint64>(_stext)),
- align_up_page(reinterpret_cast<uint64>(_kernel_end)),
- };
-
- /* Validate each range is canonical */
- auto check_kernel_half = [](const VaRange& r) {
- if (r.start >= r.end) {
- kernel_panic("kaslr: invalid VA range", r.name);
- }
- if (!is_sv39_kernel_half(r.start) || !is_sv39_kernel_half(r.end - 1)) {
- kernel_panic("kaslr: non-canonical kernel VA range", r.name);
- }
- };
-
- check_kernel_half(direct_map);
- check_kernel_half(vmemmap);
- check_kernel_half(kernel_img);
-
- /* Validate no overlaps */
- if (ranges_overlap(direct_map, kernel_img)) {
- kernel_panic("kaslr: direct-map overlaps kernel image");
- }
- if (ranges_overlap(vmemmap, kernel_img)) {
- kernel_panic("kaslr: vmemmap overlaps kernel image");
- }
- if (ranges_overlap(direct_map, vmemmap)) {
- kernel_panic("kaslr: direct-map overlaps vmemmap");
- }
-
- /* Mark validation success */
- g_kaslr_layout.canonical_ok = true;
- g_kaslr_layout.overlap_ok = true;
-
- /* 7. Logging according to CONFIG_KASLR_LOG_LEVEL */
- if (kKaslrLogLevel >= 1) {
- /* Minimal logging: just the seed and slot (release mode) */
- kprintf("[boot][kaslr] policy_id=%u source=%s slot=%llu\n",
- g_kaslr_layout.policy_id,
- random_seed_source_name(rsrc),
- slot);
- }
-
- if (kKaslrLogLevel >= 2) {
- /* Debug logging: full ranges and hashes */
- kprintf("[boot][kaslr] seed=0x%llx seed_hash=0x%llx\n",
- seed, seed_hash);
- kprintf("[boot][kaslr] direct-map=[0x%llx,0x%llx)\n",
- direct_map.start, direct_map.end);
- kprintf("[boot][kaslr] vmemmap=[0x%llx,0x%llx)\n",
- vmemmap.start, vmemmap.end);
- kprintf("[boot][kaslr] kernel-image=[0x%llx,0x%llx)\n",
- kernel_img.start, kernel_img.end);
- }
-
-#else /* CONFIG_KASLR disabled */
- g_kaslr_layout.seed = 0;
- g_kaslr_layout.seed_hash = 0;
- g_kaslr_layout.source = KaslrSeedSource::kCycle;
- g_kaslr_layout.slot = 0;
- g_kaslr_layout.slide_bytes = 0;
- g_kaslr_layout.policy_id = kKaslrPolicyId;
- g_kaslr_layout.direct_map_base = kDirectMapBaseDefault;
- g_kaslr_layout.vmemmap_base = kVmemmapBaseDefault;
- g_kaslr_layout.canonical_ok = true;
- g_kaslr_layout.overlap_ok = true;
-
- g_direct_map_base = kDirectMapBaseDefault;
- g_vmemmap_base = kVmemmapBaseDefault;
-
- if (kKaslrLogLevel >= 1) {
- kprintf("[boot][kaslr] disabled policy_id=%u\n",
- g_kaslr_layout.policy_id);
- }
-#endif
-}
-
-/* ================================================================
- * Public entry point
- * ================================================================ */
-void kaslr_init()
-{
- kaslr_layout_compute();
-}
-
-} // namespace arch