diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-10-16 02:39:56 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-10-16 02:39:56 +0800 |
| commit | 8cace3f05003c6cb4d38c36890055f03151c2ad4 (patch) | |
| tree | aa739deaac0266f17c4e91b333957501cb1ea2e9 /include | |
| parent | 3ad39e9878310e5317ee73c9b353c1e2c1c5c4ee (diff) | |
| download | lume-8cace3f05003c6cb4d38c36890055f03151c2ad4.tar.gz lume-8cace3f05003c6cb4d38c36890055f03151c2ad4.tar.xz | |
Remove old code
Signed-off-by: Richard Qin <richard.qin.x@gmail.com>
Diffstat (limited to 'include')
95 files changed, 0 insertions, 8078 deletions
diff --git a/include/libc-shim/bits/alltypes.h b/include/libc-shim/bits/alltypes.h deleted file mode 100644 index cf21a5e..0000000 --- a/include/libc-shim/bits/alltypes.h +++ /dev/null @@ -1,15 +0,0 @@ -/* Shim: provide types musl string functions need */ -#ifndef _BITS_ALLTYPES_H -#define _BITS_ALLTYPES_H - -#ifndef __cplusplus -typedef unsigned long size_t; -#endif - -typedef long ssize_t; -typedef unsigned long uintptr_t; - -/* locale_t stub — unused in kernel, but declared by some headers */ -typedef void *locale_t; - -#endif diff --git a/include/libc-shim/endian.h b/include/libc-shim/endian.h deleted file mode 100644 index 8346386..0000000 --- a/include/libc-shim/endian.h +++ /dev/null @@ -1,9 +0,0 @@ -/* Shim: endianness for musl string functions */ -#ifndef _ENDIAN_H -#define _ENDIAN_H - -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#define __BYTE_ORDER __LITTLE_ENDIAN /* RISC-V is LE */ - -#endif diff --git a/include/libc-shim/features.h b/include/libc-shim/features.h deleted file mode 100644 index a3466c8..0000000 --- a/include/libc-shim/features.h +++ /dev/null @@ -1,12 +0,0 @@ -/* Shim: musl expects this header */ -#ifndef _FEATURES_H -#define _FEATURES_H - -/* weak_alias: musl uses this for symbol aliasing (e.g. __memrchr -> memrchr) */ -#define weak_alias(old, new) \ - extern __typeof(old) new __attribute__((__weak__, __alias__(#old))) - -/* hidden attribute used by some musl sources */ -#define hidden __attribute__((__visibility__("hidden"))) - -#endif diff --git a/include/libc-shim/limits.h b/include/libc-shim/limits.h deleted file mode 100644 index a1d546e..0000000 --- a/include/libc-shim/limits.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Shim: limits for musl string functions (memmem uses SIZE_MAX) */ -#ifndef _LIMITS_H -#define _LIMITS_H - -#define CHAR_BIT 8 -#define UCHAR_MAX 255 -#define SCHAR_MAX 127 -#define SCHAR_MIN (-128) -#define INT_MAX 2147483647 -#define INT_MIN (-INT_MAX - 1) -#define UINT_MAX 4294967295U -#define LONG_MAX 9223372036854775807L -#define LONG_MIN (-LONG_MAX - 1L) -#define ULONG_MAX 18446744073709551615UL -#define SIZE_MAX ULONG_MAX - -#endif diff --git a/include/libc-shim/stdint.h b/include/libc-shim/stdint.h deleted file mode 100644 index 650bdcf..0000000 --- a/include/libc-shim/stdint.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Shim: stdint types for musl string functions */ -#ifndef _STDINT_H -#define _STDINT_H - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long uint64_t; -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -typedef signed long int64_t; -typedef unsigned long uintptr_t; -typedef long intptr_t; - -#define UINT8_MAX 0xFF -#define UINT16_MAX 0xFFFF -#define UINT32_MAX 0xFFFFFFFFU -#define UINT64_MAX 0xFFFFFFFFFFFFFFFFUL - -#endif diff --git a/include/libc-shim/string.h b/include/libc-shim/string.h deleted file mode 100644 index 8a86304..0000000 --- a/include/libc-shim/string.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef _STRING_H -#define _STRING_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <features.h> - -#if __cplusplus >= 201103L -#define NULL nullptr -#elif defined(__cplusplus) -#define NULL 0L -#else -#define NULL ((void*)0) -#endif - -#define __NEED_size_t -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) -#define __NEED_locale_t -#endif - -#include <bits/alltypes.h> - -void *memcpy (void *__restrict, const void *__restrict, size_t); -void *memmove (void *, const void *, size_t); -void *memset (void *, int, size_t); -int memcmp (const void *, const void *, size_t); -void *memchr (const void *, int, size_t); - -char *strcpy (char *__restrict, const char *__restrict); -char *strncpy (char *__restrict, const char *__restrict, size_t); - -char *strcat (char *__restrict, const char *__restrict); -char *strncat (char *__restrict, const char *__restrict, size_t); - -int strcmp (const char *, const char *); -int strncmp (const char *, const char *, size_t); - -int strcoll (const char *, const char *); -size_t strxfrm (char *__restrict, const char *__restrict, size_t); - -char *strchr (const char *, int); -char *strrchr (const char *, int); - -size_t strcspn (const char *, const char *); -size_t strspn (const char *, const char *); -char *strpbrk (const char *, const char *); -char *strstr (const char *, const char *); -char *strtok (char *__restrict, const char *__restrict); - -size_t strlen (const char *); - -char *strerror (int); - -#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) -#include <strings.h> -#endif - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ - || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) -char *strtok_r (char *__restrict, const char *__restrict, char **__restrict); -int strerror_r (int, char *, size_t); -char *stpcpy(char *__restrict, const char *__restrict); -char *stpncpy(char *__restrict, const char *__restrict, size_t); -size_t strnlen (const char *, size_t); -char *strdup (const char *); -char *strndup (const char *, size_t); -char *strsignal(int); -char *strerror_l (int, locale_t); -int strcoll_l (const char *, const char *, locale_t); -size_t strxfrm_l (char *__restrict, const char *__restrict, size_t, locale_t); -void *memmem(const void *, size_t, const void *, size_t); -#endif - -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ - || defined(_BSD_SOURCE) -void *memccpy (void *__restrict, const void *__restrict, int, size_t); -#endif - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -char *strsep(char **, const char *); -size_t strlcat (char *, const char *, size_t); -size_t strlcpy (char *, const char *, size_t); -void explicit_bzero (void *, size_t); -#endif - -#ifdef _GNU_SOURCE -#define strdupa(x) strcpy(alloca(strlen(x)+1),x) -int strverscmp (const char *, const char *); -char *strchrnul(const char *, int); -char *strcasestr(const char *, const char *); -void *memrchr(const void *, int, size_t); -void *mempcpy(void *, const void *, size_t); -#endif - -/* musl internal symbols used across translation units */ -char *__strchrnul(const char *, int); -void *__memrchr(const void *, int, size_t); -char *__stpcpy(char *__restrict, const char *__restrict); -char *__stpncpy(char *__restrict, const char *__restrict, size_t); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/libc-shim/strings.h b/include/libc-shim/strings.h deleted file mode 100644 index b7a5ea0..0000000 --- a/include/libc-shim/strings.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _STRINGS_H -#define _STRINGS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <features.h> - -#define __NEED_size_t -#define __NEED_locale_t -#include <bits/alltypes.h> - -#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \ - || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \ - || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) -int bcmp (const void *, const void *, size_t); -void bcopy (const void *, void *, size_t); -void bzero (void *, size_t); -char *index (const char *, int); -char *rindex (const char *, int); -#endif - -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -int ffs (int); -int ffsl (long); -int ffsll (long long); -#endif - -int strcasecmp (const char *, const char *); -int strncasecmp (const char *, const char *, size_t); - -int strcasecmp_l (const char *, const char *, locale_t); -int strncasecmp_l (const char *, const char *, size_t, locale_t); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/lume/addr.h b/include/lume/addr.h deleted file mode 100644 index 572b6fe..0000000 --- a/include/lume/addr.h +++ /dev/null @@ -1,91 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Machine-Independent Address Conversion Helpers - * - * All PA↔VA conversions in MI code (mm/, kernel/, etc.) must go through - * these functions. The actual offset is provided by <arch/config.h>. - * - * Reference: docs/specs/00_conventions.md §1.1 (MI/MD separation) - */ - -#include <lume/types.h> -#include <lume/config.h> -#include <lume/addr_types.h> -#include <arch/config.h> - -/* Convert physical address to kernel virtual address (direct map). */ -inline VirtAddr pa_to_va(PhysAddr pa) -{ - return VirtAddr{pa.raw + arch::g_direct_map_base}; -} - -/* Convert kernel virtual address to physical address (direct map). */ -inline PhysAddr va_to_pa(VirtAddr va) -{ - return PhysAddr{va.raw - arch::g_direct_map_base}; -} - -/* - * Early-boot conversions pinned to the bootstrap direct-map base. - * - * Use these only before vmm_init() activates the final kernel page table. - * They are required when KASLR has already randomized g_direct_map_base, - * but the CPU is still running on the bootstrap mapping built in entry.S. - */ -inline VirtAddr boot_pa_to_va(PhysAddr pa) -{ - return VirtAddr{pa.raw + arch::kDirectMapBaseDefault}; -} - -inline PhysAddr boot_va_to_pa(VirtAddr va) -{ - return PhysAddr{va.raw - arch::kDirectMapBaseDefault}; -} - -/* Align up to page boundary */ -inline uint64 page_align_up(uint64 addr) -{ - return (addr + kPageSize - 1) & ~(kPageSize - 1); -} - -/* Align down to page boundary */ -inline uint64 page_align_down(uint64 addr) -{ - return addr & ~(kPageSize - 1); -} - -inline PhysAddr page_align_up(PhysAddr addr) -{ - return PhysAddr{page_align_up(addr.raw)}; -} - -inline PhysAddr page_align_down(PhysAddr addr) -{ - return PhysAddr{page_align_down(addr.raw)}; -} - -inline VirtAddr page_align_up(VirtAddr addr) -{ - return VirtAddr{page_align_up(addr.raw)}; -} - -inline VirtAddr page_align_down(VirtAddr addr) -{ - return VirtAddr{page_align_down(addr.raw)}; -} - -/* Convert physical address to page frame number (PFN) */ -inline Pfn pa_to_pfn(PhysAddr pa) -{ - return Pfn{pa.raw / kPageSize}; -} - -/* Convert page frame number (PFN) to physical address */ -inline PhysAddr pfn_to_pa(Pfn pfn) -{ - return PhysAddr{pfn.raw * kPageSize}; -} diff --git a/include/lume/addr_types.h b/include/lume/addr_types.h deleted file mode 100644 index 91a0779..0000000 --- a/include/lume/addr_types.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -#include <lume/types.h> - -struct PhysAddr { - uint64 raw; -}; - -struct VirtAddr { - uint64 raw; -}; - -struct Pfn { - uint64 raw; -}; - -inline constexpr PhysAddr phys_addr(uint64 raw) { return PhysAddr{raw}; } -inline constexpr VirtAddr virt_addr(uint64 raw) { return VirtAddr{raw}; } -inline constexpr Pfn pfn(uint64 raw) { return Pfn{raw}; } - -inline constexpr bool operator==(PhysAddr a, PhysAddr b) { return a.raw == b.raw; } -inline constexpr bool operator!=(PhysAddr a, PhysAddr b) { return a.raw != b.raw; } -inline constexpr bool operator==(VirtAddr a, VirtAddr b) { return a.raw == b.raw; } -inline constexpr bool operator!=(VirtAddr a, VirtAddr b) { return a.raw != b.raw; } -inline constexpr bool operator==(Pfn a, Pfn b) { return a.raw == b.raw; } -inline constexpr bool operator!=(Pfn a, Pfn b) { return a.raw != b.raw; } diff --git a/include/lume/args.h b/include/lume/args.h deleted file mode 100644 index 0562dc5..0000000 --- a/include/lume/args.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#ifndef _LINUX_ARGS_H -#define _LINUX_ARGS_H - -/* - * How do these macros work? - * - * In __COUNT_ARGS() _0 to _15 are just placeholders from the start - * in order to make sure _n is positioned over the correct number - * from 15 to 0 (depending on X, which is a variadic argument list). - * They serve no purpose other than occupying a position. Since each - * macro parameter must have a distinct identifier, those identifiers - * are as good as any. - * - * In COUNT_ARGS() we use actual integers, so __COUNT_ARGS() returns - * that as _n. - */ - -/* This counts to 15. Any more, it will return 16th argument. */ -#define __COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _n, X...) _n -#define COUNT_ARGS(X...) __COUNT_ARGS(, ##X, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) - -/* Concatenate two parameters, but allow them to be expanded beforehand. */ -#define __CONCAT(a, b) a ## b -#define CONCATENATE(a, b) __CONCAT(a, b) - -#endif /* _LINUX_ARGS_H */ diff --git a/include/lume/atomic.h b/include/lume/atomic.h deleted file mode 100644 index 6e31129..0000000 --- a/include/lume/atomic.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * lume::atomic<T> — Thin wrapper over __atomic builtins. - * - * All multi-core shared data that does NOT use a spinlock MUST use - * this wrapper instead of raw __atomic_* builtins. - * - * Reference: docs/specs/00_conventions.md §5.3 - */ - -#include <lume/types.h> - -namespace lume { - -template<typename T> -class atomic { -public: - atomic() = default; - explicit atomic(T val) : val_(val) {} - - /* Prevent copies — an atomic value has identity */ - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - - /* Load with specified memory ordering */ - T load(int order = __ATOMIC_SEQ_CST) const { - return __atomic_load_n(&val_, order); - } - - /* Store with specified memory ordering */ - void store(T desired, int order = __ATOMIC_SEQ_CST) { - __atomic_store_n(&val_, desired, order); - } - - /* Atomic exchange, returns old value */ - T exchange(T desired, int order = __ATOMIC_SEQ_CST) { - return __atomic_exchange_n(&val_, desired, order); - } - - /* Fetch-and-add, returns old value */ - T fetch_add(T delta, int order = __ATOMIC_ACQ_REL) { - return __atomic_fetch_add(&val_, delta, order); - } - - /* Fetch-and-subtract, returns old value */ - T fetch_sub(T delta, int order = __ATOMIC_ACQ_REL) { - return __atomic_fetch_sub(&val_, delta, order); - } - - /* Fetch-and-or, returns old value */ - T fetch_or(T mask, int order = __ATOMIC_ACQ_REL) { - return __atomic_fetch_or(&val_, mask, order); - } - - /* Fetch-and-and, returns old value */ - T fetch_and(T mask, int order = __ATOMIC_ACQ_REL) { - return __atomic_fetch_and(&val_, mask, order); - } - - /* Compare-and-swap. Returns true on success. */ - bool compare_exchange(T& expected, T desired, - int success_order = __ATOMIC_ACQ_REL, - int failure_order = __ATOMIC_ACQUIRE) { - return __atomic_compare_exchange_n(&val_, &expected, desired, - false, success_order, failure_order); - } - -private: - T val_ = 0; -}; - -} // namespace lume diff --git a/include/lume/bitops.h b/include/lume/bitops.h deleted file mode 100644 index 4227ca3..0000000 --- a/include/lume/bitops.h +++ /dev/null @@ -1,120 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Bit Operations — portable kernel bit manipulation utilities - * - * Provides ctz, clz, ffs, fls and related operations. - * All implementations are manual (no __builtin_ctz) to avoid - * generating libgcc __ctzdi2/__clzdi2 calls in freestanding. - */ - -#include <lume/types.h> - -namespace lume { - -/* ------------------------------------------------------------------ */ -/* Count Trailing Zeros (ctz) */ -/* Returns the number of trailing 0-bits in val. */ -/* Precondition: val != 0 (undefined if val == 0). */ -/* ------------------------------------------------------------------ */ - -static inline int ctz32(uint32 val) -{ - int n = 0; - if (!(val & 0x0000FFFFU)) { n += 16; val >>= 16; } - if (!(val & 0x000000FFU)) { n += 8; val >>= 8; } - if (!(val & 0x0000000FU)) { n += 4; val >>= 4; } - if (!(val & 0x00000003U)) { n += 2; val >>= 2; } - if (!(val & 0x00000001U)) { n += 1; } - return n; -} - -static inline int ctz64(uint64 val) -{ - if (static_cast<uint32>(val) != 0) { - return ctz32(static_cast<uint32>(val)); - } - return 32 + ctz32(static_cast<uint32>(val >> 32)); -} - -/* ------------------------------------------------------------------ */ -/* Count Leading Zeros (clz) */ -/* Returns the number of leading 0-bits in val. */ -/* Precondition: val != 0 (undefined if val == 0). */ -/* ------------------------------------------------------------------ */ - -static inline int clz32(uint32 val) -{ - int n = 0; - if (!(val & 0xFFFF0000U)) { n += 16; val <<= 16; } - if (!(val & 0xFF000000U)) { n += 8; val <<= 8; } - if (!(val & 0xF0000000U)) { n += 4; val <<= 4; } - if (!(val & 0xC0000000U)) { n += 2; val <<= 2; } - if (!(val & 0x80000000U)) { n += 1; } - return n; -} - -static inline int clz64(uint64 val) -{ - if (static_cast<uint32>(val >> 32) != 0) { - return clz32(static_cast<uint32>(val >> 32)); - } - return 32 + clz32(static_cast<uint32>(val)); -} - -/* ------------------------------------------------------------------ */ -/* Find First Set (ffs) — 1-indexed, returns 0 if val == 0 */ -/* ------------------------------------------------------------------ */ - -static inline int ffs32(uint32 val) -{ - return val ? ctz32(val) + 1 : 0; -} - -static inline int ffs64(uint64 val) -{ - return val ? ctz64(val) + 1 : 0; -} - -/* ------------------------------------------------------------------ */ -/* Find Last Set (fls) — 1-indexed, returns 0 if val == 0 */ -/* Returns the position of the highest set bit. */ -/* ------------------------------------------------------------------ */ - -static inline int fls32(uint32 val) -{ - return val ? 32 - clz32(val) : 0; -} - -static inline int fls64(uint64 val) -{ - return val ? 64 - clz64(val) : 0; -} - -/* ------------------------------------------------------------------ */ -/* Order (log2) — returns floor(log2(val)), val must be > 0 */ -/* ------------------------------------------------------------------ */ - -static inline int ilog2_32(uint32 val) -{ - return fls32(val) - 1; -} - -static inline int ilog2_64(uint64 val) -{ - return fls64(val) - 1; -} - -/* ------------------------------------------------------------------ */ -/* Power-of-two test */ -/* ------------------------------------------------------------------ */ - -static inline bool is_power_of_2(uint64 val) -{ - return val != 0 && (val & (val - 1)) == 0; -} - -} /* namespace lume */ diff --git a/include/lume/chardev.h b/include/lume/chardev.h deleted file mode 100644 index be81ab9..0000000 --- a/include/lume/chardev.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * chardev.h — Character device abstraction - * - * Minimal Linux-style cdev registry: each character device has a - * major/minor number and a file_operations table. - */ - -#include <lume/types.h> -#include <lume/list.h> - -struct file_operations; - -/* ================================================================== */ -/* MKDEV / MAJOR / MINOR */ -/* ================================================================== */ - -inline constexpr uint32 MKDEV(uint32 ma, uint32 mi) { - return (ma << 8) | (mi & 0xFF); -} -inline constexpr uint32 MAJOR(uint32 dev) { return dev >> 8; } -inline constexpr uint32 MINOR(uint32 dev) { return dev & 0xFF; } - -/* ================================================================== */ -/* cdev — character device descriptor */ -/* ================================================================== */ - -struct cdev { - const char* name; - uint32 dev; /* MKDEV(major, minor) */ - const file_operations* fops; - list_node list; /* global cdev list */ -}; - -/* ================================================================== */ -/* API */ -/* ================================================================== */ - -void cdev_init(); -void cdev_register(cdev* dev); -cdev* cdev_find(uint32 dev); diff --git a/include/lume/clone.h b/include/lume/clone.h deleted file mode 100644 index 156bae4..0000000 --- a/include/lume/clone.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Linux-compatible clone(2) flags. - * - * Only the flags relevant to current and near-future use are defined. - * Reference: include/uapi/linux/sched.h - */ - -#include <lume/types.h> - -/* Signal mask stored in low byte of clone flags */ -inline constexpr uint64 CSIGNAL = 0x000000ffULL; - -/* Sharing flags */ -inline constexpr uint64 CLONE_VM = 0x00000100ULL; // Share address space -inline constexpr uint64 CLONE_FS = 0x00000200ULL; // Share fs info -inline constexpr uint64 CLONE_FILES = 0x00000400ULL; // Share file descriptors -inline constexpr uint64 CLONE_SIGHAND = 0x00000800ULL; // Share signal handlers -inline constexpr uint64 CLONE_PIDFD = 0x00001000ULL; // pidfd -inline constexpr uint64 CLONE_PTRACE = 0x00002000ULL; // Trace child -inline constexpr uint64 CLONE_VFORK = 0x00004000ULL; // Parent blocks until child exits/execs -inline constexpr uint64 CLONE_PARENT = 0x00008000ULL; // Same parent as cloner -inline constexpr uint64 CLONE_THREAD = 0x00010000ULL; // Same thread group -inline constexpr uint64 CLONE_NEWNS = 0x00020000ULL; // New mount namespace -inline constexpr uint64 CLONE_SYSVSEM = 0x00040000ULL; // Share SysV semaphore undo -inline constexpr uint64 CLONE_SETTLS = 0x00080000ULL; // Set TLS -inline constexpr uint64 CLONE_PARENT_SETTID = 0x00100000ULL; // Write TID to parent -inline constexpr uint64 CLONE_CHILD_CLEARTID = 0x00200000ULL; // Clear TID on child exit -inline constexpr uint64 CLONE_DETACHED = 0x00400000ULL; // Unused, historical -inline constexpr uint64 CLONE_CHILD_SETTID = 0x01000000ULL; // Write TID to child diff --git a/include/lume/compiler.h b/include/lume/compiler.h deleted file mode 100644 index 243f0de..0000000 --- a/include/lume/compiler.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#ifndef _LUME_COMPILER_H -#define _LUME_COMPILER_H - -/* - * Minimal compiler primitives used across LumeOS. - * - * Provides only what current code actually references: - * - READ_ONCE / WRITE_ONCE memory access opacity for concurrent code - * (rbtree.h, rbtree_augmented.h) - * - likely / unlikely branch hints for hot/cold paths - * - * Implementation mirrors Linux's semantics — same surface, same effect — - * without pulling in Linux's compiler_types.h cascade (KASAN/KCSAN/KMSAN - * sanitizer attribute machinery, BTF type tags, hardened-usercopy hooks). - * LumeOS doesn't build with those sanitizers, so the simpler form is - * sufficient and keeps the dependency graph flat. - */ - -/* Branch prediction hints */ -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) - -/* Compile-time barrier — prevent the compiler from reordering memory - * accesses across this point. Not a CPU fence; for CPU ordering use - * the architecture-specific fence intrinsics. */ -#define barrier() __asm__ __volatile__("" ::: "memory") - -/* - * __always_inline — force the compiler to actually inline a function, - * overriding -fno-inline / -Os / size heuristics. Used by rbtree helper - * templates whose performance depends on the call being inlined into - * the iterating loop. - */ -#define __always_inline inline __attribute__((__always_inline__)) - -/* - * READ_ONCE / WRITE_ONCE — opaque single-access memory operations. - * - * The volatile cast prevents the compiler from: - * - merging adjacent reads/writes to the same location, - * - splitting a load into multiple narrower loads, - * - hoisting reads out of a loop (or sinking writes past one). - * - * Used in lock-free / cross-CPU shared data paths (rbtree color writes, - * future RCU pointers, atomic flag polls). Does NOT imply any CPU-side - * memory ordering — pair with smp_mb()/acquire/release for that. - */ -#define READ_ONCE(x) (*(const volatile __typeof__(x) *)&(x)) -#define WRITE_ONCE(x, val) (*(volatile __typeof__(x) *)&(x) = (val)) - -#endif /* _LUME_COMPILER_H */ diff --git a/include/lume/config.h b/include/lume/config.h deleted file mode 100644 index bde717a..0000000 --- a/include/lume/config.h +++ /dev/null @@ -1,100 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * LumeOS Global Compile-Time Configuration - * - * All kernel-wide tuning constants live here. - * Architecture-specific constants live in <arch/config.h>. - * - * This header is safe to include from both C++ and assembly files. - * Assembly-visible constants use #define; C++ code gets typed constexpr. - * - * Values are injected by the build system via -DCONFIG_xxx flags - * (see scripts/Kconfig.mk). The #ifndef guards below provide - * safe defaults so the header is self-contained for IDE analysis. - * - * Reference: docs/specs/00_conventions.md §1.3 - */ - -/* ================================================================ - * Defaults — only used when CONFIG_xxx is NOT supplied by -D flag. - * In a normal build, scripts/Kconfig.mk always provides them. - * ================================================================ */ - -#ifndef CONFIG_NR_CPUS -#define CONFIG_NR_CPUS 8 -#endif - -#ifndef CONFIG_PAGE_SIZE -#define CONFIG_PAGE_SIZE 4096 -#endif - -#ifndef CONFIG_MAX_ORDER -#define CONFIG_MAX_ORDER 11 -#endif - -#ifndef CONFIG_KERNEL_STACK_SIZE -#define CONFIG_KERNEL_STACK_SIZE 16384 -#endif - -#ifndef CONFIG_HZ -#define CONFIG_HZ 100 -#endif - -#ifndef CONFIG_NR_PRIORITIES -#define CONFIG_NR_PRIORITIES 32 -#endif - -#ifndef CONFIG_DEFAULT_PRIORITY -#define CONFIG_DEFAULT_PRIORITY (CONFIG_NR_PRIORITIES / 2) -#endif - -#ifndef CONFIG_IDLE_PRIORITY -#define CONFIG_IDLE_PRIORITY (CONFIG_NR_PRIORITIES - 1) -#endif - -#ifndef CONFIG_DEFAULT_TIMESLICE -#define CONFIG_DEFAULT_TIMESLICE (CONFIG_HZ / 10) -#endif - -#ifndef CONFIG_KASLR_POLICY_ID -#define CONFIG_KASLR_POLICY_ID 0 /* Default: basic KASLR policy */ -#endif - -#ifndef CONFIG_KASLR_LOG_LEVEL -#define CONFIG_KASLR_LOG_LEVEL 1 /* 0=off, 1=minimal, 2=debug */ -#endif - -/* ================================================================ - * Legacy compatibility aliases (shared with assembly) - * ================================================================ */ -#define LUME_MAX_CPUS CONFIG_NR_CPUS -#define LUME_PAGE_SIZE CONFIG_PAGE_SIZE - -#ifndef __ASSEMBLER__ - -#include <lume/types.h> - -/* Maximum number of CPUs supported by the kernel. - * Compile-time limit for static arrays (boot stacks, per-cpu data). - * Actual CPU count is detected at runtime via FDT. */ -inline constexpr int kMaxCpus = CONFIG_NR_CPUS; - -/* Virtual memory page size (4KB, matching SV39 base page). */ -inline constexpr uint64 kPageSize = CONFIG_PAGE_SIZE; - -/* Page shift: log2(kPageSize). Used for PFN ↔ PA conversions. */ -inline constexpr int kPageShift = 12; // 4096 = 1 << 12 - -/* KASLR policy ID and logging level (build-time configurable) */ -inline constexpr uint32 kKaslrPolicyId = CONFIG_KASLR_POLICY_ID; -inline constexpr int kKaslrLogLevel = CONFIG_KASLR_LOG_LEVEL; - -#include <arch/config.h> - -using arch::kPhysStart; - -#endif /* __ASSEMBLER__ */
\ No newline at end of file diff --git a/include/lume/console.h b/include/lume/console.h deleted file mode 100644 index af187a6..0000000 --- a/include/lume/console.h +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * console.h — Kernel console abstraction - * - * Two-phase design following Linux: - * - * Phase 1 (early boot): - * early_putc() → direct UART MMIO write. Used before MMU and - * before the console registry is ready. kprintf() and panic - * use this path. - * - * Phase 2 (runtime): - * struct console registered via register_console(). printk/klog - * emit through the console driver chain. Multiple consoles can - * be registered (e.g., UART + framebuffer). - * - * Reference: Linux include/linux/console.h - */ - -#include <lume/types.h> -#include <lume/list.h> - -/* ================================================================== */ -/* Early console (Phase 1 — direct UART access) */ -/* ================================================================== */ - -extern "C" void early_putc(char c); -extern "C" void early_puts(const char* s); -extern "C" void console_set_mmu_enabled(); - -/* Early UART discovery via raw FDT parsing. */ -void console_early_init(uint64 fdt_paddr); - -/* Full console initialization. Maps MMIO. */ -void console_init(); - -/* - * Notify console that the runtime kernel page table is active. - * After this point early_putc() must use runtime direct-map base - * instead of the bootstrap fixed base. - */ -void console_use_runtime_mapping(); - -/* ================================================================== */ -/* struct console (Phase 2 — registered console drivers) */ -/* ================================================================== */ - -inline constexpr int CON_PRINTBUFFER = (1 << 0); /* Replay klog on register */ -inline constexpr int CON_ENABLED = (1 << 1); -inline constexpr int CON_BOOT = (1 << 2); /* Early boot console */ - -struct console { - const char* name; - void (*write)(console* con, const char* s, unsigned int count); - int (*setup)(console* con, char* options); - int flags; - int index; - void* data; /* driver private data */ - list_node list; -}; - -/* Register / unregister a console driver */ -void register_console(console* con); -void unregister_console(console* con); - -/* - * Write to all registered consoles. - * Falls back to early_putc() if no console is registered. - */ -void console_write_all(const char* s, int count); - -/* Check if any console is registered */ -bool console_drivers_registered(); diff --git a/include/lume/container_of.h b/include/lume/container_of.h deleted file mode 100644 index a6889eb..0000000 --- a/include/lume/container_of.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * container_of.h — Recover containing struct from member pointer - * - * Equivalent to Linux include/linux/container_of.h. - */ - -#include <lume/types.h> - -#define container_of(ptr, type, member) \ - reinterpret_cast<type*>( \ - reinterpret_cast<uintptr>(ptr) - \ - reinterpret_cast<uintptr>(&(reinterpret_cast<type*>(0)->member))) diff --git a/include/lume/dcache.h b/include/lume/dcache.h deleted file mode 100644 index a31402e..0000000 --- a/include/lume/dcache.h +++ /dev/null @@ -1,143 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * dcache.h — Directory entry cache - * - * Modeled after Linux include/linux/dcache.h. - * Reference: docs/vfs/03_dentry.md - */ - -#include <lume/types.h> -#include <lume/list.h> -#include <lume/atomic.h> -#include <lume/fs_types.h> -#include <kernel/sync/spinlock.h> - -struct inode; -struct super_block; -struct dentry; -struct dentry_operations; -struct path; - -/* ================================================================== */ -/* qstr — quick string (name + precomputed hash + length) */ -/* ================================================================== */ - -struct qstr { - union { - struct { - uint32 hash; - uint32 len; - }; - uint64 hash_len; - }; - const char* name; -}; - -uint32 full_name_hash(const char* name, uint32 len); - -/* ================================================================== */ -/* dentry */ -/* ================================================================== */ - -inline constexpr int DNAME_INLINE_LEN = 40; - -struct dentry { - /* ---- RCU / lookup hot fields ---- */ - unsigned int d_flags; - dentry* d_parent; - qstr d_name; - inode* d_inode; - unsigned char d_iname[DNAME_INLINE_LEN]; - - /* ---- Ref lookup ---- */ - const dentry_operations* d_op; - super_block* d_sb; - unsigned long d_time; - void* d_fsdata; - - /* ---- Refcount + lock ---- */ - lume::atomic<int32> d_lockref; - Spinlock d_lock; - - /* ---- Tree linkage ---- */ - list_node d_lru; - list_node d_child; /* Linkage in parent->d_children */ - list_head d_children; /* Children of this dentry */ - - /* ---- Inode alias ---- */ - list_node d_alias; /* Linkage in inode->i_dentry */ -}; - -/* ================================================================== */ -/* dentry_operations */ -/* ================================================================== */ - -struct dentry_operations { - int (*d_revalidate)(dentry* de, unsigned int flags); - int (*d_hash)(const dentry* de, qstr* name); - int (*d_compare)(const dentry* parent, unsigned int len, - const char* str, const qstr* name); - int (*d_delete)(const dentry* de); - int (*d_init)(dentry* de); - void (*d_release)(dentry* de); - void (*d_iput)(dentry* de, inode* ip); -}; - -/* ================================================================== */ -/* Dentry helpers */ -/* ================================================================== */ - -inline bool d_is_negative(const dentry* de) { - return (de->d_flags & DCACHE_ENTRY_TYPE) == DCACHE_MISS_TYPE; -} -inline bool d_is_positive(const dentry* de) { - return !d_is_negative(de); -} -inline bool d_is_dir(const dentry* de) { - return (de->d_flags & DCACHE_ENTRY_TYPE) == DCACHE_DIRECTORY_TYPE; -} -inline bool d_is_reg(const dentry* de) { - return (de->d_flags & DCACHE_ENTRY_TYPE) == DCACHE_REGULAR_TYPE; -} -inline bool d_is_symlink(const dentry* de) { - return (de->d_flags & DCACHE_ENTRY_TYPE) == DCACHE_SYMLINK_TYPE; -} -inline bool d_mountpoint(const dentry* de) { - return (de->d_flags & DCACHE_MOUNTED) != 0; -} -inline bool d_is_root(const dentry* de) { - return de == de->d_parent; -} - -inline inode* d_inode_ptr(const dentry* de) { - return de->d_inode; -} - -/* ================================================================== */ -/* Dcache API */ -/* ================================================================== */ - -dentry* d_alloc(dentry* parent, const qstr* name); -dentry* d_alloc_anon(super_block* sb); -void d_instantiate(dentry* de, inode* ip); -dentry* d_make_root(inode* root_inode); -void d_add(dentry* de, inode* ip); -dentry* d_lookup(const dentry* parent, const qstr* name); -dentry* dget(dentry* de); -void dput(dentry* de); -void d_drop(dentry* de); -void d_delete(dentry* de); -char* d_path(const path* p, char* buf, int buflen); - -/* Set dentry type flags based on inode mode */ -void d_set_type(dentry* de, uint32 i_mode); - -/* ================================================================== */ -/* Dcache init */ -/* ================================================================== */ - -void dcache_init(); diff --git a/include/lume/device.h b/include/lume/device.h deleted file mode 100644 index 46e22e4..0000000 --- a/include/lume/device.h +++ /dev/null @@ -1,75 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Driver model: device, device_driver, bus_type. - * - * Mirrors Linux include/linux/device.h. Every hardware unit embeds a - * `device` and binds to a `device_driver` via a `bus_type` that knows - * how to match the two. Buses we will have: - * - platform: FDT-described memory-mapped devices (this commit) - * - virtio: virtio-mmio devices (P5 of storage_stack.md) - * - * Reference: docs/specs/storage_stack.md §4.3 - */ - -#include <lume/types.h> -#include <lume/list.h> -#include <lume/kobject.h> -#include <kernel/sync/spinlock.h> - -struct bus_type; -struct device_driver; - -struct device { - kobject kobj; // embedded; first member by convention - device* parent; - const char* init_name; // used until kobj.name is set - bus_type* bus; - device_driver* driver; - void* driver_data; - void* platform_data; - uint32 devt; // for char/block dev_t allocation - list_node bus_list; // node in bus->devices - list_node driver_list; // node in driver->devices -}; - -struct device_driver { - const char* name; - bus_type* bus; - int (*probe)(device*); - void (*remove)(device*); - list_node bus_node; // node in bus->drivers - list_node devices; // head of devices bound to this driver -}; - -struct bus_type { - const char* name; - int (*match)(device*, device_driver*); - /* If non-null, this is the bus-level probe dispatcher. It is called - * before drv->probe and is responsible for downcasting device/driver - * to the concrete bus type and forwarding (e.g. platform_dispatch). */ - int (*probe)(device*); - list_node devices; - list_node drivers; - Spinlock lock; - bool registered; -}; - -int bus_register (bus_type* bus); - -/* device_initialize: kobject_init the embedded kobj with the generic - * device_ktype. device_register calls this automatically if the caller - * hasn't already. Separate entry point for callers that want a half- - * initialized device (so they can take refs before adding). */ -void device_initialize(device* dev); -int device_register (device* dev); -void device_unregister(device* dev); - -int driver_register (device_driver* drv); -void driver_unregister(device_driver* drv); - -/* Convenience accessor — name from kobject if set, else init_name. */ -const char* dev_name(const device* dev); diff --git a/include/lume/device_node.h b/include/lume/device_node.h deleted file mode 100644 index e35f22d..0000000 --- a/include/lume/device_node.h +++ /dev/null @@ -1,64 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * DeviceNode — FDT object tree node - * - * Each DeviceNode represents a single node in the unflattened device tree. - * Nodes form a parent-children hierarchy via intrusive linked lists. - * After unflattening, the tree is globally read-only and requires no locks. - * - * Created when Slab is available. - * - * Reference: docs/specs/fdt.md §3.2 - */ - -#include <lume/types.h> -#include <lume/list.h> -#include <lume/fdt_prop.h> - -class DeviceNode { -public: - // Construction / destruction (used by FdtManager::unflatten) - DeviceNode(DeviceNode *parent, const char *name); - ~DeviceNode(); - - // --- Property access --- - - // Look up a property by name. Returns nullptr if not found. - const FdtProperty *get_prop(const char *name) const; - - // Convenience helpers that decode the property value. - // Return default_val when the property does not exist. - uint32 get_prop_u32(const char *name, uint32 default_val = 0) const; - uint64 get_prop_u64(const char *name, uint64 default_val = 0) const; - const char *get_prop_string(const char *name) const; - - // --- Child traversal --- - - // Find a direct child by name. Returns nullptr if not found. - DeviceNode *find_child(const char *name); - - // Invoke callback for every direct child. - void for_each_child(void (*callback)(DeviceNode *)); - - // --- Internal (used by FdtManager to build the tree) --- - void add_child(DeviceNode *child); - void add_prop(FdtProperty *prop); - - // --- Accessors for tree traversal --- - const char *get_name() const { return name_; } - list_node *children_list_head() { return children_list_.next; } - list_node *children_list_sentinel() { return &children_list_; } - - // sibling_link_ offset needed by container_of in fdt.cc - list_node sibling_link_; // Link in parent's children_list_ - -private: - const char *name_; // Node name (e.g. "memory@80000000") - DeviceNode *parent_; // Parent node (nullptr for root) - list_node children_list_; // Head of the children linked list - list_node props_list_; // Head of the property linked list -}; diff --git a/include/lume/driver.h b/include/lume/driver.h deleted file mode 100644 index a8bd787..0000000 --- a/include/lume/driver.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * driver.h — boot-time driver probing entry point. - * - * The actual driver-model primitives (kobject, device, bus_type, - * platform_device, platform_driver) live in their own headers: - * <lume/kobject.h>, <lume/device.h>, <lume/platform_device.h>. - * - * This header just exposes the single boot entry point that - * kernel_main() calls after the slab allocator + FDT unflatten are - * ready. The implementation lives in drivers/base/platform.cc. - * - * Reference: docs/specs/storage_stack.md §4 - */ - -/* Register the platform bus, register every linker-set platform_driver, - * walk the FDT, and instantiate a platform_device for each compatible - * match. Each device is bound to its driver via the platform bus - * match/probe path. Returns after all probes have run. */ -void driver_probe_all(); diff --git a/include/lume/elf.h b/include/lume/elf.h deleted file mode 100644 index 772ad97..0000000 --- a/include/lume/elf.h +++ /dev/null @@ -1,150 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * ELF64 Type Definitions — Minimal set for loading executables - * AND for the kernel's own .rela.dyn relocation walk at boot. - * - * Follows the ELF specification (Tool Interface Standard, TIS). - * Only includes what's needed for static ELF64 executable loading. - * - * Reference: https://refspecs.linuxfoundation.org/elf/elf.pdf - */ - -#include <lume/types.h> - -/* ================================================================== */ -/* Basic ELF types */ -/* ================================================================== */ - -using Elf64_Addr = uint64; -using Elf64_Off = uint64; -using Elf64_Half = uint16; -using Elf64_Word = uint32; -using Elf64_Sword = int32; -using Elf64_Xword = uint64; -using Elf64_Sxword = int64; - -/* ================================================================== */ -/* ELF Header */ -/* ================================================================== */ - -inline constexpr int EI_NIDENT = 16; - -struct Elf64_Ehdr { - uint8 e_ident[EI_NIDENT]; /* ELF identification */ - Elf64_Half e_type; /* Object file type */ - Elf64_Half e_machine; /* Machine type */ - Elf64_Word e_version; /* Object file version */ - Elf64_Addr e_entry; /* Entry point address */ - Elf64_Off e_phoff; /* Program header table offset */ - Elf64_Off e_shoff; /* Section header table offset */ - Elf64_Word e_flags; /* Processor-specific flags */ - Elf64_Half e_ehsize; /* ELF header size */ - Elf64_Half e_phentsize; /* Program header entry size */ - Elf64_Half e_phnum; /* Number of program headers */ - Elf64_Half e_shentsize; /* Section header entry size */ - Elf64_Half e_shnum; /* Number of section headers */ - Elf64_Half e_shstrndx; /* Section name string table index */ -}; - -/* e_ident[] indices */ -inline constexpr int EI_MAG0 = 0; -inline constexpr int EI_MAG1 = 1; -inline constexpr int EI_MAG2 = 2; -inline constexpr int EI_MAG3 = 3; -inline constexpr int EI_CLASS = 4; -inline constexpr int EI_DATA = 5; -inline constexpr int EI_VERSION = 6; -inline constexpr int EI_OSABI = 7; - -/* e_ident[] magic */ -inline constexpr uint8 ELFMAG0 = 0x7f; -inline constexpr uint8 ELFMAG1 = 'E'; -inline constexpr uint8 ELFMAG2 = 'L'; -inline constexpr uint8 ELFMAG3 = 'F'; - -/* e_ident[EI_CLASS] */ -inline constexpr uint8 ELFCLASS64 = 2; - -/* e_ident[EI_DATA] */ -inline constexpr uint8 ELFDATA2LSB = 1; /* Little-endian */ - -/* e_type */ -inline constexpr Elf64_Half ET_EXEC = 2; /* Executable */ -inline constexpr Elf64_Half ET_DYN = 3; /* Shared object (PIE) */ - -/* e_machine */ -inline constexpr Elf64_Half EM_RISCV = 243; - -/* ================================================================== */ -/* Program Header */ -/* ================================================================== */ - -struct Elf64_Phdr { - Elf64_Word p_type; /* Segment type */ - Elf64_Word p_flags; /* Segment flags */ - Elf64_Off p_offset; /* File offset */ - Elf64_Addr p_vaddr; /* Virtual address */ - Elf64_Addr p_paddr; /* Physical address (unused) */ - Elf64_Xword p_filesz; /* Size in file */ - Elf64_Xword p_memsz; /* Size in memory (>= p_filesz, diff is BSS) */ - Elf64_Xword p_align; /* Alignment */ -}; - -/* p_type values */ -inline constexpr Elf64_Word PT_NULL = 0; -inline constexpr Elf64_Word PT_LOAD = 1; -inline constexpr Elf64_Word PT_DYNAMIC = 2; -inline constexpr Elf64_Word PT_INTERP = 3; -inline constexpr Elf64_Word PT_NOTE = 4; -inline constexpr Elf64_Word PT_PHDR = 6; -inline constexpr Elf64_Word PT_GNU_STACK = 0x6474e551; - -/* p_flags values */ -inline constexpr Elf64_Word PF_X = 0x1; /* Execute */ -inline constexpr Elf64_Word PF_W = 0x2; /* Write */ -inline constexpr Elf64_Word PF_R = 0x4; /* Read */ - -/* ================================================================== */ -/* Auxiliary Vector types */ -/* ================================================================== */ - -struct Elf64_auxv_t { - uint64 a_type; - uint64 a_val; -}; - -inline constexpr uint64 AT_NULL = 0; -inline constexpr uint64 AT_PHDR = 3; -inline constexpr uint64 AT_PHENT = 4; -inline constexpr uint64 AT_PHNUM = 5; -inline constexpr uint64 AT_PAGESZ = 6; -inline constexpr uint64 AT_ENTRY = 9; -inline constexpr uint64 AT_UID = 11; -inline constexpr uint64 AT_EUID = 12; -inline constexpr uint64 AT_GID = 13; -inline constexpr uint64 AT_EGID = 14; -inline constexpr uint64 AT_RANDOM = 25; -inline constexpr uint64 AT_BASE = 7; /* PIE load base address */ - -/* ================================================================== */ -/* RELA relocation entry — used by the kernel's own .rela.dyn walk */ -/* at boot (relocate_kernel in arch/riscv/mm/init.cc). */ -/* ================================================================== */ - -struct Elf64_Rela { - Elf64_Addr r_offset; /* link-time VA of the slot to patch */ - Elf64_Xword r_info; /* r_sym << 32 | r_type */ - Elf64_Sxword r_addend; /* link-time value of the target */ -}; - -#define ELF64_R_TYPE(info) ((info) & 0xFFFFFFFFULL) - -/* RISC-V relocation types — only the ones a PIE-linked kernel emits - * into .rela.dyn under `-shared -Bsymbolic`. */ -inline constexpr uint32 R_RISCV_NONE = 0; -inline constexpr uint32 R_RISCV_64 = 2; -inline constexpr uint32 R_RISCV_RELATIVE = 3; diff --git a/include/lume/errno.h b/include/lume/errno.h deleted file mode 100644 index f3bf09f..0000000 --- a/include/lume/errno.h +++ /dev/null @@ -1,186 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#ifndef _LUME_ERRNO_H -#define _LUME_ERRNO_H - -/* - * Error codes — numeric values aligned with Linux's asm-generic/errno-base.h, - * asm-generic/errno.h, and linux/errno.h (kernel-internal codes 512+). - * - * Userspace-visible codes (1..133) match POSIX / Linux exactly so a LumeOS - * binary returning -EINVAL to a user program receives the same number Linux - * would. Kernel-internal codes (>= 512) follow Linux's convention of being - * out of POSIX range; they are translated to a user-visible code (typically - * EINTR) before crossing into user mode. - * - * Defined as plain #define so this header is usable from C, C++, and - * assembly (the macros expand to integer literals, no types). - */ - -/* ===== Base errors (asm-generic/errno-base.h equivalent) ===== */ -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Argument list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain */ -#define ERANGE 34 /* Math result not representable */ - -/* ===== Extended errors (asm-generic/errno.h equivalent) ===== */ -#define EDEADLK 35 /* Resource deadlock would occur */ -#define ENAMETOOLONG 36 /* File name too long */ -#define ENOLCK 37 /* No record locks available */ -#define ENOSYS 38 /* Invalid system call number */ -#define ENOTEMPTY 39 /* Directory not empty */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ -#define EDEADLOCK EDEADLK -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Cannot access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Linking in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define EILSEQ 84 /* Illegal byte sequence */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define ENOTSUP EOPNOTSUPP -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ -#define ENOMEDIUM 123 /* No medium found */ -#define EMEDIUMTYPE 124 /* Wrong medium type */ -#define ECANCELED 125 /* Operation Canceled */ -#define ENOKEY 126 /* Required key not available */ -#define EKEYEXPIRED 127 /* Key has expired */ -#define EKEYREVOKED 128 /* Key has been revoked */ -#define EKEYREJECTED 129 /* Key was rejected by service */ -#define EOWNERDEAD 130 /* Owner died (for robust mutexes) */ -#define ENOTRECOVERABLE 131 /* State not recoverable */ -#define ERFKILL 132 /* Operation not possible due to RF-kill */ -#define EHWPOISON 133 /* Memory page has hardware error */ - -/* ===== Kernel-internal errors (linux/errno.h equivalent, >= 512) ===== - * These should never be seen by user programs. signal/syscall layer - * translates them to a user-visible code (typically EINTR) before - * returning to userspace. - */ -#define ERESTARTSYS 512 -#define ERESTARTNOINTR 513 -#define ERESTARTNOHAND 514 /* restart if no signal handler */ -#define ENOIOCTLCMD 515 /* No ioctl command */ -#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */ -#define EPROBE_DEFER 517 /* Driver requests probe retry */ -#define EOPENSTALE 518 /* open() found a stale dentry */ -#define ENOPARAM 519 /* Parameter not supported */ - -/* NFSv3 reserved range (521..531) */ -#define EBADHANDLE 521 /* Illegal NFS file handle */ -#define ENOTSYNC 522 /* Update synchronization mismatch */ -#define EBADCOOKIE 523 /* Cookie is stale */ -#define ENOTSUPP 524 /* Operation is not supported */ -#define ETOOSMALL 525 /* Buffer or request is too small */ -#define ESERVERFAULT 526 /* An untranslatable error occurred */ -#define EBADTYPE 527 /* Type not supported by server */ -#define EJUKEBOX 528 /* Request initiated, will not complete before timeout */ -#define EIOCBQUEUED 529 /* iocb queued, will get completion event */ -#define ERECALLCONFLICT 530 /* conflict with recalled state */ -#define ENOGRACE 531 /* NFS file lock reclaim refused */ - -#endif /* _LUME_ERRNO_H */ diff --git a/include/lume/fdt.h b/include/lume/fdt.h deleted file mode 100644 index 626cc48..0000000 --- a/include/lume/fdt.h +++ /dev/null @@ -1,85 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * FdtManager — Flattened Device Tree parser - * - * Two-phase design: - * Phase 1 (Early Scan): Static methods that walk the raw FDT blob - * without any memory allocation. Used before PMM is available. - * Phase 2 (Unflatten): Builds a persistent C++ DeviceNode object - * tree once Slab is ready. The tree is then globally read-only. - * - * Concurrency: all init is done by BSP in the single-core window. - * After unflattening the tree is immutable — no locks required. - * - * Reference: docs/specs/fdt.md - */ - -#include <lume/device_node.h> -#include <lume/types.h> - -class FdtManager { -public: - // Construct with the physical address of the FDT blob. - // Called via Placement New in fdt_init(). - FdtManager(uint64 fdt_paddr); - - // --- Phase 1: Early scan (static, allocation-free) --- - - // Extract physical memory base and size from the /memory node. - // Panics if the FDT is invalid or /memory is missing. - static void early_scan_mem(uint64 fdt_paddr, uint64 *base, uint64 *size); - - // Extract the UART base address and size by matching compatible = "ns16550a". - // Falls back to platform default on failure. - static void early_scan_uart(uint64 fdt_paddr, uint64 *uart_addr, - uint64 *uart_size); - - static void early_scan_kaslr(uint64 fdt_paddr, uint64 *seed); - - // --- Phase 2: Object tree construction (requires Slab) --- - - // Walk the FDT blob and build the DeviceNode tree. - void unflatten(); - - // --- Query interface (read-only after unflatten) --- - - // Find the first node whose "compatible" property contains the string. - // Returns nullptr if no match. - DeviceNode *find_compatible(const char *compat_string); - - // Look up a node by its full path (e.g. "/soc/uart@10000000"). - // Returns nullptr if not found. - DeviceNode *get_node_by_path(const char *path); - - // Return the stored FDT physical address. - uint64 get_paddr() const { return fdt_paddr_; } - -private: - uint64 fdt_paddr_; // Physical address of the FDT blob - bool is_unflattened_ = false; // True after unflatten() completes - DeviceNode *root_ = nullptr; // Root of the unflattened tree -}; - -/* Global FDT manager singleton (Placement New, see global_init.md §3.1) */ -extern FdtManager *g_fdt; - -// --- Public free-function API --- - -// Save FDT address and validate magic. Called early by BSP. -void fdt_init(uint64 fdt_paddr); - -// Build the DeviceNode object tree. Requires Slab. -void fdt_unflatten(); - -// Driver probing helpers (delegate to g_fdt). -DeviceNode *fdt_find_compatible(const char *compat_string); -DeviceNode *fdt_get_node_by_path(const char *path); - -// Early scan wrappers (delegate to FdtManager static methods). -void fdt_early_get_mem_info(uint64 *base, uint64 *size); -void fdt_early_get_uart_info(uint64 *uart_addr, uint64 *uart_size); -void fdt_early_get_kaslr_seed(uint64 *seed); diff --git a/include/lume/fdt_prop.h b/include/lume/fdt_prop.h deleted file mode 100644 index f8a263c..0000000 --- a/include/lume/fdt_prop.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * FDT Property - * - * Represents a single property within a DeviceNode (e.g. "reg", - * "compatible"). The value pointer points directly into the - * original FDT blob — no copies are made. - * - * Reference: docs/specs/fdt.md §3.1 - */ - -#include <lume/types.h> -#include <lume/list.h> - -struct FdtProperty { - const char *name; // Property name (points into FDT strings block) - const void *value; // Raw property data (points into FDT struct block) - int len; // Length of value in bytes - list_node link; // Intrusive link into DeviceNode's property list -}; diff --git a/include/lume/fdtable.h b/include/lume/fdtable.h deleted file mode 100644 index 6159519..0000000 --- a/include/lume/fdtable.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * fdtable.h — Per-task file descriptor table - * - * Modeled after Linux include/linux/fdtable.h. - * Reference: docs/vfs/05_fdtable.md - */ - -#include <lume/types.h> -#include <lume/atomic.h> -#include <kernel/sync/spinlock.h> - -struct file; - -/* ================================================================== */ -/* files_struct — per-task open file table */ -/* ================================================================== */ - -inline constexpr int NR_OPEN_DEFAULT = 256; - -struct files_struct { - lume::atomic<int32> count; /* Reference count (CLONE_FILES) */ - Spinlock file_lock; - - int next_fd; /* Hint for next free fd */ - int max_fds; /* Current max (= NR_OPEN_DEFAULT) */ - file* fd_array[NR_OPEN_DEFAULT]; - uint64 close_on_exec_init[(NR_OPEN_DEFAULT + 63) / 64]; - uint64 open_fds_init[(NR_OPEN_DEFAULT + 63) / 64]; -}; - -/* ================================================================== */ -/* API */ -/* ================================================================== */ - -files_struct* alloc_files_struct(); -void put_files_struct(files_struct* files); -files_struct* dup_fd(files_struct* old_files); - -int alloc_fd(files_struct* files, unsigned int start); -void fd_install(files_struct* files, int fd, file* fp); -file* fcheck(files_struct* files, int fd); -int close_fd(files_struct* files, int fd); -int do_dup2(files_struct* files, int oldfd, int newfd, int flags); -void do_close_on_exec(files_struct* files); diff --git a/include/lume/features.h b/include/lume/features.h deleted file mode 100644 index 85cfb72..0000000 --- a/include/lume/features.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _FEATURES_H -#define _FEATURES_H - -#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) -#define _BSD_SOURCE 1 -#endif - -#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ - && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ - && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) -#define _BSD_SOURCE 1 -#define _XOPEN_SOURCE 700 -#endif - -#if __STDC_VERSION__ >= 199901L -#define __restrict restrict -#elif !defined(__GNUC__) -#define __restrict -#endif - -#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) -#define __inline inline -#elif !defined(__GNUC__) -#define __inline -#endif - -#if __STDC_VERSION__ >= 201112L -#elif defined(__GNUC__) -#define _Noreturn __attribute__((__noreturn__)) -#else -#define _Noreturn -#endif - -#define __REDIR(x,y) __typeof__(x) x __asm__(#y) - -#endif diff --git a/include/lume/file.h b/include/lume/file.h deleted file mode 100644 index 349059b..0000000 --- a/include/lume/file.h +++ /dev/null @@ -1,132 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * file.h — Open file description + file_operations + path + vfsmount - * - * Modeled after Linux include/linux/fs.h struct file / file_operations. - * Reference: docs/vfs/04_file.md - */ - -#include <lume/types.h> -#include <lume/atomic.h> -#include <lume/fs_types.h> -#include <kernel/sync/spinlock.h> - -struct inode; -struct dentry; -struct super_block; -struct address_space; -struct dir_context; -struct VmAreaStruct; -struct kstat; - -/* ================================================================== */ -/* vfsmount (public part) */ -/* ================================================================== */ - -struct vfsmount { - dentry* mnt_root; - super_block* mnt_sb; - int mnt_flags; -}; - -vfsmount* mntget(vfsmount* mnt); -void mntput(vfsmount* mnt); - -/* ================================================================== */ -/* path */ -/* ================================================================== */ - -struct path { - vfsmount* mnt; - dentry* de; /* Linux calls this 'dentry' but that conflicts in C++ */ -}; - -void path_get(const path* p); -void path_put(const path* p); - -/* ================================================================== */ -/* file */ -/* ================================================================== */ - -struct file_operations; - -struct file { - Spinlock f_lock; - uint32 f_mode; /* FMODE_* */ - const file_operations* f_op; - address_space* f_mapping; - void* private_data; - inode* f_inode; - unsigned int f_flags; /* O_* */ - - path f_path; - - int64 f_pos; - lume::atomic<int32> f_count; -}; - -/* ================================================================== */ -/* Accessors */ -/* ================================================================== */ - -inline inode* file_inode(const file* f) { return f->f_inode; } -inline dentry* file_dentry(const file* f) { return f->f_path.de; } - -file* get_file(file* f); -file* alloc_empty_file(int flags); -void fput(file* fp); - -/* ================================================================== */ -/* dir_context (for iterate_shared / getdents64) */ -/* ================================================================== */ - -struct dir_context; -using filldir_t = bool (*)(dir_context* ctx, const char* name, int namelen, - int64 offset, uint64 ino, unsigned int d_type); - -struct dir_context { - filldir_t actor; - int64 pos; -}; - -/* ================================================================== */ -/* file_operations */ -/* ================================================================== */ - -struct file_operations { - int64 (*llseek)(file* fp, int64 offset, int whence); - int64 (*read)(file* fp, char* buf, uint64 count, int64* pos); - int64 (*write)(file* fp, const char* buf, uint64 count, int64* pos); - int (*iterate_shared)(file* fp, dir_context* ctx); - uint32 (*poll)(file* fp, void* pt); - long (*unlocked_ioctl)(file* fp, unsigned int cmd, uint64 arg); - int (*mmap)(file* fp, VmAreaStruct* vma); - int (*open)(inode* ip, file* fp); - int (*flush)(file* fp); - int (*release)(inode* ip, file* fp); - int (*fsync)(file* fp, int64 start, int64 end, int datasync); -}; - -/* ================================================================== */ -/* VFS read/write/seek */ -/* ================================================================== */ - -int64 vfs_read(file* fp, char* buf, uint64 count, int64* pos); -int64 vfs_write(file* fp, const char* buf, uint64 count, int64* pos); -int64 vfs_llseek(file* fp, int64 offset, int whence); -int vfs_fstat(file* fp, kstat* stat); - -/* Generic helpers for simple fs */ -int64 generic_file_llseek(file* fp, int64 offset, int whence); - -/* ================================================================== */ -/* path helpers */ -/* ================================================================== */ - -inline bool path_equal(const path* a, const path* b) { - return a->mnt == b->mnt && a->de == b->de; -} diff --git a/include/lume/fs.h b/include/lume/fs.h deleted file mode 100644 index 8dac552..0000000 --- a/include/lume/fs.h +++ /dev/null @@ -1,310 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * fs.h — Core VFS data structures - * - * Defines super_block, inode, address_space, and their operations. - * Modeled after Linux include/linux/fs.h + include/linux/fs/super_types.h. - * - * Reference: docs/vfs/01_super_block.md, docs/vfs/02_inode.md - */ - -#include <lume/types.h> -#include <lume/list.h> -#include <lume/atomic.h> -#include <lume/fs_types.h> -#include <kernel/sync/spinlock.h> - -/* Forward declarations */ -struct super_block; -struct inode; -struct dentry; -struct file; -struct vfsmount; -struct path; -struct kstat; -struct iattr; -struct file_operations; -struct inode_operations; -struct dentry_operations; -struct dir_context; -struct pipe_inode_info; -struct VmAreaStruct; -struct Page; - -/* ================================================================== */ -/* address_space_operations */ -/* ================================================================== */ - -struct address_space_operations { - int (*read_folio)(file* fp, Page* page); - int (*write_begin)(struct address_space* mapping, int64 pos, - unsigned len, Page** pagep, void** fsdata); - int (*write_end)(struct address_space* mapping, int64 pos, - unsigned len, unsigned copied, - Page* page, void* fsdata); -}; - -/* ================================================================== */ -/* address_space */ -/* ================================================================== */ - -struct address_space { - inode* host; - const address_space_operations* a_ops; - uint64 nrpages; - uint64 flags; - Spinlock i_private_lock; -}; - -/* ================================================================== */ -/* super_operations */ -/* ================================================================== */ - -struct super_operations { - inode* (*alloc_inode)(super_block* sb); - void (*destroy_inode)(inode* ip); - void (*free_inode)(inode* ip); - - void (*dirty_inode)(inode* ip, int flags); - int (*write_inode)(inode* ip, bool sync); - int (*drop_inode)(inode* ip); - void (*evict_inode)(inode* ip); - void (*put_super)(super_block* sb); - int (*sync_fs)(super_block* sb, int wait); - int (*statfs)(dentry* de, struct kstatfs* buf); - void (*umount_begin)(super_block* sb); -}; - -/* ================================================================== */ -/* file_system_type */ -/* ================================================================== */ - -struct file_system_type { - const char* name; - int fs_flags; - super_block* (*mount)(file_system_type* type, int flags, - const char* dev_name, void* data); - void (*kill_sb)(super_block* sb); - list_node fs_list; -}; - -int register_filesystem(file_system_type* fs); -file_system_type* get_fs_type(const char* name); - -/* ================================================================== */ -/* super_block */ -/* ================================================================== */ - -struct mount; - -struct super_block { - list_node s_list; - uint64 s_dev; - uint8 s_blocksize_bits; - uint64 s_blocksize; - int64 s_maxbytes; - file_system_type* s_type; - const super_operations* s_op; - - uint64 s_flags; - uint64 s_magic; - dentry* s_root; - - char s_id[32]; - void* s_fs_info; - - uint32 s_time_gran; - int64 s_time_min; - int64 s_time_max; - - Spinlock s_inode_list_lock; - list_head s_inodes; - - lume::atomic<int32> s_active; - int s_count; - - mount* s_mounts; - uint32 s_max_links; - const dentry_operations* s_d_op; -}; - -/* ================================================================== */ -/* inode */ -/* ================================================================== */ - -struct inode { - /* ---- Path-walk hot fields ---- */ - uint32 i_mode; - uint32 i_flags; - uint32 i_uid; - uint32 i_gid; - - const inode_operations* i_op; - super_block* i_sb; - address_space* i_mapping; - - /* ---- Stat data ---- */ - uint64 i_ino; - uint32 i_nlink; /* Use set_nlink/inc_nlink/drop_nlink */ - uint32 i_rdev; - int64 i_size; - - int64 i_atime_sec; - int64 i_mtime_sec; - int64 i_ctime_sec; - uint32 i_atime_nsec; - uint32 i_mtime_nsec; - uint32 i_ctime_nsec; - uint32 i_generation; - - Spinlock i_lock; - unsigned short i_bytes; - uint8 i_blkbits; - int64 i_blocks; - - /* ---- State ---- */ - uint32 i_state; - - /* ---- Lists ---- */ - list_node i_sb_list; - list_head i_dentry; - - /* ---- Counters ---- */ - lume::atomic<int32> i_count; - lume::atomic<int32> i_writecount; - - /* ---- File ops ---- */ - const file_operations* i_fop; - - /* ---- Embedded address_space ---- */ - address_space i_data; - - /* ---- Type-specific ---- */ - union { - pipe_inode_info* i_pipe; - char* i_link; - uint32 i_dir_seq; - }; - - void* i_private; -}; - -/* ================================================================== */ -/* inode_operations */ -/* ================================================================== */ - -struct inode_operations { - dentry* (*lookup)(inode* dir, dentry* de, unsigned int flags); - int (*create)(inode* dir, dentry* de, uint32 mode, bool excl); - int (*link)(dentry* old_de, inode* dir, dentry* new_de); - int (*unlink)(inode* dir, dentry* de); - int (*symlink)(inode* dir, dentry* de, const char* target); - int (*mkdir)(inode* dir, dentry* de, uint32 mode); - int (*rmdir)(inode* dir, dentry* de); - int (*mknod)(inode* dir, dentry* de, uint32 mode, uint32 rdev); - int (*rename)(inode* old_dir, dentry* old_de, - inode* new_dir, dentry* new_de, unsigned int flags); - int (*setattr)(dentry* de, iattr* attr); - int (*getattr)(const path* p, kstat* stat, uint32 request_mask, - unsigned int query_flags); - const char* (*get_link)(dentry* de, inode* ip); - int (*permission)(inode* ip, int mask); -}; - -/* ================================================================== */ -/* Inode API */ -/* ================================================================== */ - -inode* new_inode(super_block* sb); -inode* iget(super_block* sb, uint64 ino); -void iput(inode* ip); -void ihold(inode* ip); -void mark_inode_dirty(inode* ip); - -void set_nlink(inode* ip, uint32 nlink); -void inc_nlink(inode* ip); -void drop_nlink(inode* ip); -void clear_nlink(inode* ip); - -void inode_init_owner(inode* ip, const inode* dir, uint32 mode); - -/* Generic helpers used by simple filesystems */ -void generic_fillattr(inode* ip, kstat* stat); - -/* ================================================================== */ -/* kstat (matches oscomp ABI layout exactly) */ -/* ================================================================== */ - -struct kstat { - uint64 st_dev; - uint64 st_ino; - uint32 st_mode; - uint32 st_nlink; - uint32 st_uid; - uint32 st_gid; - uint64 st_rdev; - uint64 __pad; - int64 st_size; - int32 st_blksize; - int32 __pad2; - int64 st_blocks; - int64 st_atime_sec; - int64 st_atime_nsec; - int64 st_mtime_sec; - int64 st_mtime_nsec; - int64 st_ctime_sec; - int64 st_ctime_nsec; - uint32 __unused[2]; -}; - -struct kstatfs { - int64 f_type; - int64 f_bsize; - uint64 f_blocks; - uint64 f_bfree; - uint64 f_bavail; - uint64 f_files; - uint64 f_ffree; - int32 f_fsid[2]; - int64 f_namelen; - int64 f_frsize; - int64 f_flags; - int64 f_spare[4]; -}; - -/* ================================================================== */ -/* iattr (for setattr) */ -/* ================================================================== */ - -struct iattr { - unsigned int ia_valid; /* ATTR_* flags */ - uint32 ia_mode; - uint32 ia_uid; - uint32 ia_gid; - int64 ia_size; - int64 ia_atime_sec; - int64 ia_atime_nsec; - int64 ia_mtime_sec; - int64 ia_mtime_nsec; - int64 ia_ctime_sec; - int64 ia_ctime_nsec; -}; - -/* ATTR_* flags */ -inline constexpr uint32 ATTR_MODE = (1U << 0); -inline constexpr uint32 ATTR_UID = (1U << 1); -inline constexpr uint32 ATTR_GID = (1U << 2); -inline constexpr uint32 ATTR_SIZE = (1U << 3); -inline constexpr uint32 ATTR_ATIME = (1U << 4); -inline constexpr uint32 ATTR_MTIME = (1U << 5); -inline constexpr uint32 ATTR_CTIME = (1U << 6); - -/* ================================================================== */ -/* VFS init */ -/* ================================================================== */ - -void vfs_init(); diff --git a/include/lume/fs_struct.h b/include/lume/fs_struct.h deleted file mode 100644 index ba643b5..0000000 --- a/include/lume/fs_struct.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * fs_struct.h — Per-task filesystem context (cwd, root) - * - * Modeled after Linux include/linux/fs_struct.h. - * Reference: docs/vfs/05_fdtable.md - */ - -#include <lume/types.h> -#include <lume/atomic.h> -#include <lume/file.h> /* struct path */ -#include <kernel/sync/spinlock.h> - -/* ================================================================== */ -/* fs_struct */ -/* ================================================================== */ - -struct fs_struct { - lume::atomic<int32> count; /* Reference count (CLONE_FS) */ - Spinlock lock; - int umask; /* File creation mask */ - path root; /* Root directory */ - path pwd; /* Current working directory */ -}; - -/* ================================================================== */ -/* API */ -/* ================================================================== */ - -fs_struct* alloc_fs_struct(); -void put_fs_struct(fs_struct* fs); -fs_struct* copy_fs_struct(const fs_struct* old_fs); - -void set_fs_root(fs_struct* fs, const path* p); -void set_fs_pwd(fs_struct* fs, const path* p); diff --git a/include/lume/fs_types.h b/include/lume/fs_types.h deleted file mode 100644 index 767f37c..0000000 --- a/include/lume/fs_types.h +++ /dev/null @@ -1,197 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * fs_types.h — File mode constants, open flags, seek constants - * - * All values match Linux asm-generic so musl/busybox binaries work. - * Reference: docs/vfs/02_inode.md, docs/vfs/04_file.md - */ - -#include <lume/types.h> - -/* ================================================================== */ -/* S_IF* — file type in inode::i_mode upper bits */ -/* ================================================================== */ - -inline constexpr uint32 S_IFMT = 0170000; -inline constexpr uint32 S_IFSOCK = 0140000; -inline constexpr uint32 S_IFLNK = 0120000; -inline constexpr uint32 S_IFREG = 0100000; -inline constexpr uint32 S_IFBLK = 0060000; -inline constexpr uint32 S_IFDIR = 0040000; -inline constexpr uint32 S_IFCHR = 0020000; -inline constexpr uint32 S_IFIFO = 0010000; - -inline constexpr uint32 S_ISUID = 04000; -inline constexpr uint32 S_ISGID = 02000; -inline constexpr uint32 S_ISVTX = 01000; - -inline constexpr uint32 S_IRWXU = 00700; -inline constexpr uint32 S_IRUSR = 00400; -inline constexpr uint32 S_IWUSR = 00200; -inline constexpr uint32 S_IXUSR = 00100; -inline constexpr uint32 S_IRWXG = 00070; -inline constexpr uint32 S_IRGRP = 00040; -inline constexpr uint32 S_IWGRP = 00020; -inline constexpr uint32 S_IXGRP = 00010; -inline constexpr uint32 S_IRWXO = 00007; -inline constexpr uint32 S_IROTH = 00004; -inline constexpr uint32 S_IWOTH = 00002; -inline constexpr uint32 S_IXOTH = 00001; - -inline bool S_ISREG(uint32 m) { return (m & S_IFMT) == S_IFREG; } -inline bool S_ISDIR(uint32 m) { return (m & S_IFMT) == S_IFDIR; } -inline bool S_ISCHR(uint32 m) { return (m & S_IFMT) == S_IFCHR; } -inline bool S_ISBLK(uint32 m) { return (m & S_IFMT) == S_IFBLK; } -inline bool S_ISFIFO(uint32 m) { return (m & S_IFMT) == S_IFIFO; } -inline bool S_ISLNK(uint32 m) { return (m & S_IFMT) == S_IFLNK; } -inline bool S_ISSOCK(uint32 m) { return (m & S_IFMT) == S_IFSOCK; } - -/* ================================================================== */ -/* O_* — open(2) flags */ -/* ================================================================== */ - -inline constexpr int O_RDONLY = 00; -inline constexpr int O_WRONLY = 01; -inline constexpr int O_RDWR = 02; -inline constexpr int O_ACCMODE = 03; -inline constexpr int O_CREAT = 0100; -inline constexpr int O_EXCL = 0200; -inline constexpr int O_NOCTTY = 0400; -inline constexpr int O_TRUNC = 01000; -inline constexpr int O_APPEND = 02000; -inline constexpr int O_NONBLOCK = 04000; -inline constexpr int O_DSYNC = 010000; -inline constexpr int O_DIRECTORY = 0200000; -inline constexpr int O_NOFOLLOW = 0400000; -inline constexpr int O_CLOEXEC = 02000000; - -/* ================================================================== */ -/* AT_* — *at() syscall dirfd constants */ -/* ================================================================== */ - -inline constexpr int AT_FDCWD = -100; -inline constexpr int AT_REMOVEDIR = 0x200; -inline constexpr int AT_SYMLINK_NOFOLLOW = 0x100; -inline constexpr int AT_EMPTY_PATH = 0x1000; - -/* ================================================================== */ -/* SEEK_* — lseek(2) whence */ -/* ================================================================== */ - -inline constexpr int SEEK_SET = 0; -inline constexpr int SEEK_CUR = 1; -inline constexpr int SEEK_END = 2; - -/* ================================================================== */ -/* FMODE_* — internal file mode flags */ -/* ================================================================== */ - -inline constexpr uint32 FMODE_READ = (1U << 0); -inline constexpr uint32 FMODE_WRITE = (1U << 1); -inline constexpr uint32 FMODE_LSEEK = (1U << 2); -inline constexpr uint32 FMODE_PREAD = (1U << 3); -inline constexpr uint32 FMODE_PWRITE = (1U << 4); -inline constexpr uint32 FMODE_EXEC = (1U << 5); -inline constexpr uint32 FMODE_CAN_READ = (1U << 17); -inline constexpr uint32 FMODE_CAN_WRITE = (1U << 18); -inline constexpr uint32 FMODE_OPENED = (1U << 19); -inline constexpr uint32 FMODE_CREATED = (1U << 20); -inline constexpr uint32 FMODE_STREAM = (1U << 21); - -/* ================================================================== */ -/* MAY_* — permission check flags */ -/* ================================================================== */ - -inline constexpr int MAY_EXEC = 0x00000001; -inline constexpr int MAY_WRITE = 0x00000002; -inline constexpr int MAY_READ = 0x00000004; -inline constexpr int MAY_OPEN = 0x00000020; -inline constexpr int MAY_CHDIR = 0x00000040; - -/* ================================================================== */ -/* DT_* — directory entry types (for getdents64) */ -/* ================================================================== */ - -inline constexpr uint8 DT_UNKNOWN = 0; -inline constexpr uint8 DT_FIFO = 1; -inline constexpr uint8 DT_CHR = 2; -inline constexpr uint8 DT_DIR = 4; -inline constexpr uint8 DT_BLK = 6; -inline constexpr uint8 DT_REG = 8; -inline constexpr uint8 DT_LNK = 10; -inline constexpr uint8 DT_SOCK = 12; - -/* ================================================================== */ -/* SB_* — super_block flags */ -/* ================================================================== */ - -inline constexpr uint64 SB_RDONLY = (1ULL << 0); -inline constexpr uint64 SB_NOSUID = (1ULL << 1); -inline constexpr uint64 SB_NODEV = (1ULL << 2); -inline constexpr uint64 SB_NOEXEC = (1ULL << 3); -inline constexpr uint64 SB_SYNCHRONOUS = (1ULL << 4); -inline constexpr uint64 SB_NOATIME = (1ULL << 10); -inline constexpr uint64 SB_NODIRATIME = (1ULL << 11); -inline constexpr uint64 SB_SILENT = (1ULL << 15); -inline constexpr uint64 SB_KERNMOUNT = (1ULL << 22); -inline constexpr uint64 SB_LAZYTIME = (1ULL << 25); -inline constexpr uint64 SB_ACTIVE = (1ULL << 30); - -/* ================================================================== */ -/* MNT_* — mount flags */ -/* ================================================================== */ - -inline constexpr int MNT_NOSUID = 0x01; -inline constexpr int MNT_NODEV = 0x02; -inline constexpr int MNT_NOEXEC = 0x04; -inline constexpr int MNT_NOATIME = 0x08; -inline constexpr int MNT_RELATIME = 0x20; -inline constexpr int MNT_READONLY = 0x40; -inline constexpr int MNT_INTERNAL = 0x4000; - -/* ================================================================== */ -/* Inode state flags */ -/* ================================================================== */ - -inline constexpr uint32 I_NEW = (1U << 0); -inline constexpr uint32 I_DIRTY_SYNC = (1U << 4); -inline constexpr uint32 I_DIRTY_DATASYNC = (1U << 5); -inline constexpr uint32 I_DIRTY_PAGES = (1U << 6); -inline constexpr uint32 I_WILL_FREE = (1U << 7); -inline constexpr uint32 I_FREEING = (1U << 8); -inline constexpr uint32 I_CLEAR = (1U << 9); -inline constexpr uint32 I_REFERENCED = (1U << 10); -inline constexpr uint32 I_DIRTY_TIME = (1U << 12); -inline constexpr uint32 I_CREATING = (1U << 15); - -inline constexpr uint32 I_DIRTY_INODE = I_DIRTY_SYNC | I_DIRTY_DATASYNC; -inline constexpr uint32 I_DIRTY = I_DIRTY_INODE | I_DIRTY_PAGES; - -/* ================================================================== */ -/* DCACHE_* — dentry flags */ -/* ================================================================== */ - -inline constexpr uint32 DCACHE_OP_HASH = (1U << 0); -inline constexpr uint32 DCACHE_OP_COMPARE = (1U << 1); -inline constexpr uint32 DCACHE_OP_REVALIDATE = (1U << 2); -inline constexpr uint32 DCACHE_DISCONNECTED = (1U << 5); -inline constexpr uint32 DCACHE_REFERENCED = (1U << 6); -inline constexpr uint32 DCACHE_CANT_MOUNT = (1U << 8); -inline constexpr uint32 DCACHE_MOUNTED = (1U << 15); -inline constexpr uint32 DCACHE_ENTRY_TYPE = (7U << 19); -inline constexpr uint32 DCACHE_MISS_TYPE = (0U << 19); -inline constexpr uint32 DCACHE_DIRECTORY_TYPE = (2U << 19); -inline constexpr uint32 DCACHE_REGULAR_TYPE = (4U << 19); -inline constexpr uint32 DCACHE_SPECIAL_TYPE = (5U << 19); -inline constexpr uint32 DCACHE_SYMLINK_TYPE = (6U << 19); - -/* ================================================================== */ -/* FS_* — file_system_type flags */ -/* ================================================================== */ - -inline constexpr int FS_REQUIRES_DEV = 1; -inline constexpr int FS_NO_DEVICE = 2; diff --git a/include/lume/init.h b/include/lume/init.h deleted file mode 100644 index 541ab96..0000000 --- a/include/lume/init.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#ifndef _LUME_INIT_H -#define _LUME_INIT_H - -/* - * Boot-time section markers. - * - * Mirrors the subset of Linux include/linux/init.h that LumeOS uses: - * - * __init mark a function as boot-only — emitted into .init.text, - * which the kernel can later free once setup_arch / - * start_kernel have finished (LumeOS doesn't yet reclaim - * this memory, but the segment lives so future versions - * can without source changes). - * __initdata same for data, emitted into .init.data. - * asmlinkage ABI marker for C functions called from assembly. On - * RISC-V the default C ABI matches the assembly calling - * convention, so this is empty (matches Linux RISC-V). - * - * No attempt is made to mirror Linux's COMMAND_LINE_SIZE / saved_command_line - * machinery — that belongs in a future <lume/setup.h>. - */ - -#define __init __attribute__((section(".init.text"))) -#define __initdata __attribute__((section(".init.data"))) - -#ifndef asmlinkage -#define asmlinkage /* RISC-V: empty, ABI already matches */ -#endif - -#endif /* _LUME_INIT_H */ diff --git a/include/lume/irq.h b/include/lume/irq.h deleted file mode 100644 index f5f34e4..0000000 --- a/include/lume/irq.h +++ /dev/null @@ -1,84 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * IRQ Manager — Dynamic Interrupt Dispatch - * - * Drivers register ISR callbacks at init time via register_handler(). - * The MI trap layer calls dispatch() when an external interrupt arrives. - * dispatch() runs in interrupt context — handlers must be short and - * non-blocking. - * - * Lock contract: - * - lock_ protects register/unregister (cold path). - * - dispatch() is lock-free: handler pointers are published with RELEASE - * semantics and read with ACQUIRE in dispatch(). - * - Handlers must not acquire VmSpace::lock or sleep. - * - * Reference: docs/specs/trap.md §3.3 - */ - -#include <lume/atomic.h> -#include <lume/types.h> - -/* IRQ handler callback signature */ -using IrqHandler = void (*)(uint32 irq, void *arg); - -/* Abstract Interrupt Controller Interface */ -struct IrqChip { - const char* name; - uint32 (*claim)(); - void (*complete)(uint32 irq); - void (*init_ap)(); - void (*enable)(uint32 irq); - void (*disable)(uint32 irq); - void (*set_priority)(uint32 irq, uint32 priority); -}; - -class IrqManager { -public: - void init(); - - /* Register an ISR for the given IRQ number. - * Returns 0 on success, -EINVAL if irq out of range, -EBUSY if already - * registered. */ - int register_handler(uint32 irq, IrqHandler handler, void *arg); - - /* Unregister the ISR for the given IRQ number. */ - void unregister_handler(uint32 irq); - - /* Dispatch an interrupt to the registered handler. - * Called from MI trap layer in interrupt context. Lock-free. */ - void dispatch(uint32 irq); - - /* Set the active interrupt controller chip */ - void set_chip(const IrqChip* chip); - const IrqChip* get_chip() const { return chip_; } - - /* Architecture-independent claim and complete for the active IRQ chip */ - uint32 claim() const; - void complete(uint32 irq) const; - void init_ap() const; - void enable(uint32 irq) const; - void disable(uint32 irq) const; - void set_priority(uint32 irq, uint32 priority) const; - - /* Check if a handler is registered for the given IRQ. */ - bool has_handler(uint32 irq) const; - - static constexpr uint32 kMaxIrqs = 64; - -private: - struct IrqEntry { - lume::atomic<uint64> handler_ptr; // Stored as uint64 for atomic access - void *arg = nullptr; - }; - - const IrqChip* chip_ = nullptr; - IrqEntry entries_[kMaxIrqs]; -}; - -/* Global IRQ manager singleton */ -extern IrqManager g_irq_manager; diff --git a/include/lume/kbuild.h b/include/lume/kbuild.h deleted file mode 100644 index 4c3e12a..0000000 --- a/include/lume/kbuild.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#ifndef _LUME_KBUILD_H -#define _LUME_KBUILD_H - -/* - * Helpers for arch/<arch>/kernel/asm-offsets.c — 1:1 with Linux - * include/linux/kbuild.h. - * - * Trick: each DEFINE/OFFSET emits an inline-asm ".ascii" directive - * containing a literal "->" prefix. When the file is compiled with - * - * $(CC) -S asm-offsets.c -o asm-offsets.s - * - * the resulting assembly contains lines like - * - * ->KERNEL_MAP_VIRT_ADDR $0 offsetof(struct kernel_mapping, virt_addr) - * - * scripts/extract-asm-offsets.sed then rewrites those into proper - * `#define KERNEL_MAP_VIRT_ADDR 0` lines for inclusion from head.S. - * - * The benefit over hand-written #defines is that struct layout changes - * are caught at build time: rearrange a field and the asm offset - * changes automatically. - */ - -#define DEFINE(sym, val) \ - asm volatile("\n.ascii \"->" #sym " %0 " #val "\"" : : "i" (val)) - -#define BLANK() \ - asm volatile("\n.ascii \"->\"" : : ) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)) - -#define COMMENT(x) \ - asm volatile("\n.ascii \"->#" x "\"") - -#endif /* _LUME_KBUILD_H */ diff --git a/include/lume/kernel_map.h b/include/lume/kernel_map.h deleted file mode 100644 index 7eafe88..0000000 --- a/include/lume/kernel_map.h +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#ifndef _LUME_KERNEL_MAP_H -#define _LUME_KERNEL_MAP_H - -/* - * struct kernel_mapping — where the kernel image lives in physical and - * virtual memory. Field names and order match Linux's - * arch/riscv/include/asm/page.h struct kernel_mapping so that: - * - * 1. arch/riscv/kernel/head.S can do `la a1, kernel_map` then - * `REG_L a1, KERNEL_MAP_VIRT_ADDR(a1)` and read the virtual - * address. The KERNEL_MAP_* asm constants come from - * <generated/asm-offsets.h>, produced by arch/riscv/kernel/ - * asm-offsets.c at build time — re-order the struct and the - * asm offsets follow automatically. - * - * 2. arch/riscv/mm/init.c (Linux origin) populates the same fields - * with the same semantics so no source edits are needed. - */ - -#ifndef __ASSEMBLY__ - -#include <lume/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -struct kernel_mapping { - unsigned long virt_addr; - unsigned long virt_offset; - uintptr_t phys_addr; - uintptr_t size; - unsigned long va_pa_offset; - unsigned long page_offset; - unsigned long va_kernel_pa_offset; -}; - -extern struct kernel_mapping kernel_map; - -#ifdef __cplusplus -} -#endif - -#else /* __ASSEMBLY__ */ - -/* Assembly sees only the field offsets, picked up from the generated - * header. Including the C struct above would be a parse error. */ -#include <generated/asm-offsets.h> - -#endif /* __ASSEMBLY__ */ - -#endif /* _LUME_KERNEL_MAP_H */ diff --git a/include/lume/klog.h b/include/lume/klog.h deleted file mode 100644 index 69ab269..0000000 --- a/include/lume/klog.h +++ /dev/null @@ -1,200 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Kernel Logging Subsystem - * - * All kernel output goes through klog(), which formats messages into - * a fixed-size ring buffer and optionally emits them to the console. - * - * Architecture: - * vsnprintf_() ← pure formatting (mpaland/printf) - * ↓ - * KlogBuffer (ring) ← all messages stored here - * ↓ - * early_putc() (sync) ← current: synchronous UART output - * klogd thread (async) ← future: background flush thread - * /proc/kmsg ← future: userspace dmesg interface - * - * Reference: docs/specs/klog.md - */ - -#include <lume/types.h> - -/* ======================================================================== - * Log Levels (matches Linux kern_levels.h ordering) - * ======================================================================== */ - -enum KlogLevel : uint8 { - KLOG_EMERG = 0, /* System is unusable */ - KLOG_ALERT = 1, /* Action must be taken immediately */ - KLOG_CRIT = 2, /* Critical conditions */ - KLOG_ERR = 3, /* Error conditions */ - KLOG_WARN = 4, /* Warning conditions */ - KLOG_NOTICE = 5, /* Normal but significant condition */ - KLOG_INFO = 6, /* Informational */ - KLOG_DEBUG = 7, /* Debug-level messages */ -}; - -/* Log subsystems (bitmask-friendly) */ -enum KlogSubsys : uint8 { - KLOG_SUBSYS_GENERIC = 0, - KLOG_SUBSYS_SCHED = 1, - KLOG_SUBSYS_TRAP = 2, - KLOG_SUBSYS_IRQ = 3, - KLOG_SUBSYS_TIMER = 4, - KLOG_SUBSYS_VMM = 5, - KLOG_SUBSYS_PMM = 6, - KLOG_SUBSYS_SLAB = 7, - KLOG_SUBSYS_FS = 8, - KLOG_SUBSYS_DRIVER = 9, - KLOG_SUBSYS_TEST = 10, - KLOG_SUBSYS_SYSCALL = 11, /* per-syscall entry trace */ - KLOG_SUBSYS_EXEC = 12, /* ELF load / exec internals */ - KLOG_SUBSYS_SIGNAL = 13, /* signal delivery trace */ - KLOG_SUBSYS_TTY = 14, /* tty / job-control trace */ - KLOG_SUBSYS_MAX = 15, -}; - -/* Default: show everything up to INFO. DEBUG is compile-gated. */ -#ifndef KLOG_DEFAULT_LEVEL -#define KLOG_DEFAULT_LEVEL KLOG_INFO -#endif - -/* Ring buffer size: 2^KLOG_BUF_SHIFT bytes (default 64KB) */ -#ifndef KLOG_BUF_SHIFT -#define KLOG_BUF_SHIFT 16 -#endif - -#define KLOG_BUF_SIZE (1U << KLOG_BUF_SHIFT) - -/* Maximum length of a single log message (stack-allocated) */ -#define KLOG_LINE_MAX 256 - -struct KlogStats { - uint32 head; - uint32 tail; - uint32 console_tail; - uint32 dropped; - uint32 seq; -}; - -struct KlogRateLimit { - uint64 last_ts; - uint32 interval; - uint32 burst; - uint32 printed; - uint32 suppressed; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -/* ======================================================================== - * Initialization - * ======================================================================== */ - -/* Initialize the ring buffer and console backend. Call once from BSP. */ -void klog_init(void); - -/* ======================================================================== - * Core API - * ======================================================================== */ - -/* Write a leveled log message. Formats into ring buffer, then - * synchronously flushes to console if level <= current threshold. */ -__attribute__((format(printf, 2, 3))) -void klog(KlogLevel level, const char* fmt, ...); - -__attribute__((format(printf, 3, 4))) -void klog_ex(KlogLevel level, KlogSubsys subsys, const char* fmt, ...); - -/* Linux-style printk interface */ -__attribute__((format(printf, 1, 2))) -int printk(const char* fmt, ...); -int vprintk(const char* fmt, __builtin_va_list va); - -/* Set runtime log level filter. Messages above this level are - * still stored in the ring buffer but not printed to console. */ -void klog_set_level(KlogLevel level); - -void klog_set_subsys_mask(uint64 mask); -void klog_enable_subsys(KlogSubsys subsys); -void klog_disable_subsys(KlogSubsys subsys); - -/* ======================================================================== - * Ring Buffer Read (for future dmesg / /proc/kmsg) - * ======================================================================== */ - -/* Read up to 'size' bytes from the ring buffer into 'buf'. - * Returns number of bytes read. Non-destructive peek. */ -int klog_read(char* buf, int size); - -/* Read and consume entries (advances tail). */ -int klog_read_consume(char* buf, int size); - -/* Flush pending entries to console (advances console tail). */ -void klog_flush(void); - -bool klog_ratelimit(KlogRateLimit* rl, uint64 now); - -void klog_stats(KlogStats* out); - -/* ======================================================================== - * Convenience Macros - * ======================================================================== */ - -#define pr_emerg(fmt, ...) klog_ex(KLOG_EMERG, KLOG_SUBSYS_GENERIC, fmt, ##__VA_ARGS__) -#define pr_alert(fmt, ...) klog_ex(KLOG_ALERT, KLOG_SUBSYS_GENERIC, fmt, ##__VA_ARGS__) -#define pr_crit(fmt, ...) klog_ex(KLOG_CRIT, KLOG_SUBSYS_GENERIC, fmt, ##__VA_ARGS__) -#define pr_err(fmt, ...) klog_ex(KLOG_ERR, KLOG_SUBSYS_GENERIC, fmt, ##__VA_ARGS__) -#define pr_warn(fmt, ...) klog_ex(KLOG_WARN, KLOG_SUBSYS_GENERIC, fmt, ##__VA_ARGS__) -#define pr_notice(fmt, ...) klog_ex(KLOG_NOTICE, KLOG_SUBSYS_GENERIC, fmt, ##__VA_ARGS__) -#define pr_info(fmt, ...) klog_ex(KLOG_INFO, KLOG_SUBSYS_GENERIC, fmt, ##__VA_ARGS__) - -#define pr_emerg_s(subsys, fmt, ...) klog_ex(KLOG_EMERG, subsys, fmt, ##__VA_ARGS__) -#define pr_alert_s(subsys, fmt, ...) klog_ex(KLOG_ALERT, subsys, fmt, ##__VA_ARGS__) -#define pr_crit_s(subsys, fmt, ...) klog_ex(KLOG_CRIT, subsys, fmt, ##__VA_ARGS__) -#define pr_err_s(subsys, fmt, ...) klog_ex(KLOG_ERR, subsys, fmt, ##__VA_ARGS__) -#define pr_warn_s(subsys, fmt, ...) klog_ex(KLOG_WARN, subsys, fmt, ##__VA_ARGS__) -#define pr_notice_s(subsys, fmt, ...) klog_ex(KLOG_NOTICE, subsys, fmt, ##__VA_ARGS__) -#define pr_info_s(subsys, fmt, ...) klog_ex(KLOG_INFO, subsys, fmt, ##__VA_ARGS__) - -#ifdef KLOG_ENABLE_DEBUG -#define pr_debug(fmt, ...) klog_ex(KLOG_DEBUG, KLOG_SUBSYS_GENERIC, fmt, ##__VA_ARGS__) -#else -#define pr_debug(fmt, ...) do {} while (0) -#endif - -/* pr_debug_s: subsystem-tagged debug. Always compiled in (subsys is the gate); - * level KLOG_DEBUG ensures messages stay in the ring buffer but are filtered - * out of the console by default (console_level = KLOG_INFO). Toggle a subsys - * with klog_enable_subsys()/klog_disable_subsys() at runtime — or, to make - * the messages also reach the console for debugging, raise console_level - * via klog_set_level(KLOG_DEBUG). */ -#define pr_debug_s(subsys, fmt, ...) \ - klog_ex(KLOG_DEBUG, subsys, fmt, ##__VA_ARGS__) - -/* Linux kernel loglevel prefixes */ -#define KERN_SOH "\001" -#define KERN_EMERG KERN_SOH "0" -#define KERN_ALERT KERN_SOH "1" -#define KERN_CRIT KERN_SOH "2" -#define KERN_ERR KERN_SOH "3" -#define KERN_WARNING KERN_SOH "4" -#define KERN_NOTICE KERN_SOH "5" -#define KERN_INFO KERN_SOH "6" -#define KERN_DEBUG KERN_SOH "7" - -/* Boot stage log (thin wrapper over printk) */ -#define BOOT_STAGE(n, desc) \ - printk(KERN_INFO "STAGE%u %s\n", (unsigned)(n), (desc)) - -extern "C" [[noreturn]] void kernel_panic(const char* msg, const char* detail = nullptr); - -#ifdef __cplusplus -} -#endif diff --git a/include/lume/kobject.h b/include/lume/kobject.h deleted file mode 100644 index 8581d6e..0000000 --- a/include/lume/kobject.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * kobject — generic refcounted object with parent/child relationship. - * - * Mirrors Linux include/linux/kobject.h. Embedded into device, gendisk, - * request_queue, block_device, etc. Each kobject has a kobj_type that - * provides the release callback called when the last reference drops. - * - * sysfs integration is not yet implemented — the sd/sysfs_ops fields are - * reserved for future use. - * - * Reference: docs/specs/storage_stack.md §4.2 - */ - -#include <lume/types.h> -#include <lume/list.h> -#include <lume/kref.h> -#include <kernel/sync/spinlock.h> - -struct kobj_type; - -struct kobject { - const char* name; - kobject* parent; - kref refcount; - const kobj_type* ktype; - list_node entry; // node in parent->children - list_node children; // head of children list - Spinlock lock; - bool state_in_sysfs; // reserved, always false for now -}; - -struct kobj_type { - void (*release)(kobject*); - /* sysfs_ops + default_attrs: reserved for future sysfs implementation. */ -}; - -/* Initialize a kobject in place; refcount starts at 1. - * Caller must provide a non-null ktype with a valid release(). */ -void kobject_init(kobject* k, const kobj_type* type); - -/* Link `k` under `parent` (which may be null for a detached root). - * Caller passes a stable `name` pointer (e.g. a static string or an - * already-strdup'd buffer); kobject does not own the name string. */ -int kobject_add(kobject* k, kobject* parent, const char* name); - -/* Unlink from parent. Does NOT drop the final ref — caller decides - * when to kobject_put(). */ -void kobject_del(kobject* k); - -/* Bump / drop reference. */ -void kobject_get(kobject* k); -void kobject_put(kobject* k); diff --git a/include/lume/kprintf.h b/include/lume/kprintf.h deleted file mode 100644 index b158602..0000000 --- a/include/lume/kprintf.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Kernel Formatted Output — kprintf - * - * Provides printf-style formatted output for the kernel. - * Built on top of stb_sprintf for full format string support - * without any libc dependency. - * - * Output is synchronous and directed to the console (UART). - * Safe to call from any context (interrupt or process). - * - * Usage: - * kprintf("Hello %s, addr=0x%lx\n", name, addr); - */ - -#include <stdarg.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* Formatted print to console (like printf). */ -__attribute__((format(printf, 1, 2))) -int kprintf(const char* fmt, ...); - -/* Formatted print with va_list. */ -int kvprintf(const char* fmt, va_list va); - -/* Formatted snprintf into buffer. */ -__attribute__((format(printf, 3, 4))) -int ksnprintf(char* buf, int count, const char* fmt, ...); - -#ifdef __cplusplus -} -#endif diff --git a/include/lume/kref.h b/include/lume/kref.h deleted file mode 100644 index 13d53f3..0000000 --- a/include/lume/kref.h +++ /dev/null @@ -1,46 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * kref — atomic reference counting. - * - * Mirrors Linux include/linux/kref.h. Use kref_init() to set count=1, - * kref_get() / kref_put() to add/drop refs. kref_put() invokes the - * release callback when the final ref is dropped and returns 1 in that - * case. - * - * Reference: docs/specs/storage_stack.md §4.1 - */ - -#include <lume/types.h> -#include <lume/atomic.h> - -struct kref { - lume::atomic<int32> refcount; -}; - -inline void kref_init(kref* k) -{ - k->refcount.store(1, __ATOMIC_RELEASE); -} - -inline void kref_get(kref* k) -{ - k->refcount.fetch_add(1, __ATOMIC_RELAXED); -} - -inline int kref_put(kref* k, void (*release)(kref*)) -{ - if (k->refcount.fetch_sub(1, __ATOMIC_ACQ_REL) == 1) { - release(k); - return 1; - } - return 0; -} - -inline int32 kref_read(const kref* k) -{ - return k->refcount.load(__ATOMIC_RELAXED); -} diff --git a/include/lume/libfdt.h b/include/lume/libfdt.h deleted file mode 100644 index e3496e9..0000000 --- a/include/lume/libfdt.h +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _INCLUDE_LIBFDT_H_ -#define _INCLUDE_LIBFDT_H_ - -#include <lume/libfdt_env.h> -#include "../../scripts/dtc/libfdt/libfdt.h" - -#endif /* _INCLUDE_LIBFDT_H_ */ diff --git a/include/lume/libfdt_env.h b/include/lume/libfdt_env.h deleted file mode 100644 index a95fb1d..0000000 --- a/include/lume/libfdt_env.h +++ /dev/null @@ -1,78 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#ifndef LIBFDT_ENV_H -#define LIBFDT_ENV_H - -/* - * Kernel-side adapter for the standalone libfdt sources in - * scripts/dtc/libfdt/. libfdt's *.c files start with - * #include "libfdt_env.h" - * and expect this header to provide: - * - byte-swap helpers (cpu_to_fdt16/32/64, fdt16/32/64_to_cpu) - * - fdt16/32/64_t typedefs (just plain uint types — endianness is - * handled in the helpers above) - * - string / mem helpers (memcpy, memmove, memcmp, strlen, strcmp, - * strchr, strnlen, ...) - * - INT_MAX, UINT32_MAX (libfdt bounds-checks props with these) - * - size_t / uintptr_t (everywhere) - * - * LumeOS-native: no Linux <linux/...> includes. Provides the surface - * libfdt needs and nothing else. - */ - -#include <lume/types.h> /* uint16_t / uint32_t / uint64_t / size_t */ -#include <lume/limits.h> /* INT_MAX */ -#include <string.h> /* libc-shim memcpy / memcmp / strlen ... */ - -/* libfdt uses these names; both come from <lume/limits.h>. */ -#define INT32_MAX 2147483647 -#define UINT32_MAX 4294967295U - -/* libfdt's "FDT word" types — opaque big-endian-stored u16/u32/u64. - * The byte-swap helpers below are the only access path. */ -typedef uint16_t fdt16_t; -typedef uint32_t fdt32_t; -typedef uint64_t fdt64_t; - -/* - * Endianness helpers. FDT (Device Tree Blob) is big-endian by spec. - * LumeOS runs on RISC-V (little-endian) and x86 (little-endian); we - * unconditionally byte-swap. - * - * Open-coded shifts rather than __builtin_bswapN — on RISC-V without - * the Zbb extension, gcc lowers __builtin_bswap32 to a libgcc call - * (__bswapsi2 / __bswapdi2) which isn't present in a freestanding - * kernel link. Mirrors Linux's scripts/dtc/libfdt/libfdt_env.h - * which uses ___constant_swab32-style explicit shifts. */ -static inline uint16_t __lumefdt_bswap16(uint16_t x) -{ - return (uint16_t)((x << 8) | (x >> 8)); -} -static inline uint32_t __lumefdt_bswap32(uint32_t x) -{ - return ((x & 0x000000FFu) << 24) | - ((x & 0x0000FF00u) << 8) | - ((x & 0x00FF0000u) >> 8) | - ((x & 0xFF000000u) >> 24); -} -static inline uint64_t __lumefdt_bswap64(uint64_t x) -{ - return ((x & 0x00000000000000FFull) << 56) | - ((x & 0x000000000000FF00ull) << 40) | - ((x & 0x0000000000FF0000ull) << 24) | - ((x & 0x00000000FF000000ull) << 8) | - ((x & 0x000000FF00000000ull) >> 8) | - ((x & 0x0000FF0000000000ull) >> 24) | - ((x & 0x00FF000000000000ull) >> 40) | - ((x & 0xFF00000000000000ull) >> 56); -} - -#define fdt16_to_cpu(x) __lumefdt_bswap16((uint16_t)(x)) -#define cpu_to_fdt16(x) ((fdt16_t)__lumefdt_bswap16((uint16_t)(x))) -#define fdt32_to_cpu(x) __lumefdt_bswap32((uint32_t)(x)) -#define cpu_to_fdt32(x) ((fdt32_t)__lumefdt_bswap32((uint32_t)(x))) -#define fdt64_to_cpu(x) __lumefdt_bswap64((uint64_t)(x)) -#define cpu_to_fdt64(x) ((fdt64_t)__lumefdt_bswap64((uint64_t)(x))) - -#endif /* LIBFDT_ENV_H */ diff --git a/include/lume/limits.h b/include/lume/limits.h deleted file mode 100644 index a275a71..0000000 --- a/include/lume/limits.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#ifndef _LUME_LIMITS_H -#define _LUME_LIMITS_H - -/* - * Numeric limit constants — minimal subset needed by LumeOS kernel code. - * - * Values match the standard <limits.h> on all 64-bit LP64 targets, which - * is the only ABI LumeOS supports. Defined as plain integer literals so - * this header is usable from C, C++, and assembly without dragging in - * the toolchain's <limits.h> (which on hosted builds references libc - * internals we don't link against). - */ - -/* Signed/unsigned char */ -#define SCHAR_MIN (-128) -#define SCHAR_MAX 127 -#define UCHAR_MAX 255 -#define CHAR_MIN SCHAR_MIN -#define CHAR_MAX SCHAR_MAX - -/* Short */ -#define SHRT_MIN (-32768) -#define SHRT_MAX 32767 -#define USHRT_MAX 65535 - -/* Int */ -#define INT_MIN (-INT_MAX - 1) -#define INT_MAX 2147483647 -#define UINT_MAX 4294967295U - -/* Long (LP64: 64-bit) */ -#define LONG_MIN (-LONG_MAX - 1L) -#define LONG_MAX 9223372036854775807L -#define ULONG_MAX 18446744073709551615UL - -/* Long long */ -#define LLONG_MIN (-LLONG_MAX - 1LL) -#define LLONG_MAX 9223372036854775807LL -#define ULLONG_MAX 18446744073709551615ULL - -/* size_t (LP64) */ -#define SIZE_MAX ULONG_MAX -#define SSIZE_MAX LONG_MAX - -#endif /* _LUME_LIMITS_H */ diff --git a/include/lume/list.h b/include/lume/list.h deleted file mode 100644 index ed1202a..0000000 --- a/include/lume/list.h +++ /dev/null @@ -1,346 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -#include <lume/types.h> -#include <lume/container_of.h> - -/** - * @brief The node to be embedded in a struct to make it linkable. - * - * An object can be on multiple lists simultaneously by embedding multiple - * list_node members with different names. - */ -struct list_node { - list_node* prev; - list_node* next; - - /** - * @brief Initializes the node to point to itself, forming an empty list head. - */ - void init() { - prev = this; - next = this; - } - - /** - * @brief Checks if the list this node is the head of is empty. - * @return True if the list is empty, false otherwise. - */ - bool is_empty() const { - return next == this; - } -}; - -/* - * Type-safe container_of: given a pointer to a list_node member, - * recover a pointer to the enclosing object. - * Uses pointer-to-member arithmetic — no __builtin_offsetof needed. - */ -template <typename T, list_node T::*Member> -static inline T *list_entry(list_node *node) -{ - const size_t off = (size_t)(uintptr) & (((T *)nullptr)->*Member); - return reinterpret_cast<T *>(reinterpret_cast<uintptr>(node) - off); -} - -/** - * @brief A type-safe, intrusive, doubly-linked list. - * - * This class manages objects of type T that have a `list_node` member. - * It has zero runtime overhead compared to a manual C implementation and - * provides compile-time type safety. - * - * @tparam T The type of the object in the list. - * @tparam NodeMember A pointer-to-member specifying which `list_node` in T to use. - */ -template <typename T, list_node T::*NodeMember> -class List { -private: - static list_node* get_node(T* obj) { - return &(obj->*NodeMember); - } - - // NOTE: `((T*)nullptr)->*NodeMember` is technically undefined behavior in - // standard C++. However, it's a common idiom in low-level programming - // (similar to `offsetof`) that compilers typically handle correctly, - // especially with flags like `-fno-delete-null-pointer-checks`. - // The alternative (using `offsetof`) would sacrifice the compile-time - // type safety of the pointer-to-member template parameter. - static T* get_obj(list_node* node) { - constexpr size_t offset = (size_t)(uintptr) & (((T*)nullptr)->*NodeMember); - return reinterpret_cast<T*>(reinterpret_cast<uintptr>(node) - offset); - } - - static const T* get_obj(const list_node* node) { - constexpr size_t offset = (size_t)(uintptr) & (((T*)nullptr)->*NodeMember); - return reinterpret_cast<const T*>(reinterpret_cast<uintptr>(node) - offset); - } - -public: - class iterator; - class const_iterator; - - class iterator { - friend class List<T, NodeMember>; - friend class const_iterator; - - public: - iterator(list_node* node) : node_(node) {} - - T& operator*() const { return *get_obj(node_); } - T* operator->() const { return get_obj(node_); } - - iterator& operator++() { - node_ = node_->next; - return *this; - } - iterator operator++(int) { - iterator tmp = *this; - ++(*this); - return tmp; - } - - iterator& operator--() { - node_ = node_->prev; - return *this; - } - iterator operator--(int) { - iterator tmp = *this; - --(*this); - return tmp; - } - - bool operator==(const iterator& other) const { return node_ == other.node_; } - bool operator!=(const iterator& other) const { return !(*this == other); } - - private: - list_node* node_; - }; - - class const_iterator { - public: - const_iterator(const list_node* node) : node_(node) {} - const_iterator(const iterator& other) : node_(other.node_) {} - - const T& operator*() const { return *get_obj(node_); } - const T* operator->() const { return get_obj(node_); } - - const_iterator& operator++() { - node_ = node_->next; - return *this; - } - const_iterator operator++(int) { - const_iterator tmp = *this; - ++(*this); - return tmp; - } - - const_iterator& operator--() { - node_ = node_->prev; - return *this; - } - const_iterator operator--(int) { - const_iterator tmp = *this; - --(*this); - return tmp; - } - - bool operator==(const const_iterator& other) const { return node_ == other.node_; } - bool operator!=(const const_iterator& other) const { return !(*this == other); } - - private: - const list_node* node_; - }; - - List() { head_.init(); } - ~List() = default; - - // This container is intrusive and does not own the objects. - // Copying or moving it is a logical error. - List(const List&) = delete; - List& operator=(const List&) = delete; - - bool empty() const { return head_.is_empty(); } - - void push_front(T* obj) { - list_node* node = get_node(obj); - node->next = head_.next; - node->prev = &head_; - head_.next->prev = node; - head_.next = node; - } - - void push_back(T* obj) { - list_node* node = get_node(obj); - node->prev = head_.prev; - node->next = &head_; - head_.prev->next = node; - head_.prev = node; - } - - /** - * @brief Splices all elements from another list to the front of this list. - * - * Moves all elements from `other` to the beginning of `this` list in O(1) - * time. The `other` list becomes empty after the operation. - * - * @param other The list to splice from. - */ - void splice_front(List& other) { - if (other.empty()) { - return; - } - list_node* this_first = head_.next; - list_node* other_first = other.head_.next; - list_node* other_last = other.head_.prev; - - // Link other's last to this's original first - other_last->next = this_first; - this_first->prev = other_last; - - // Link this's head to other's first - head_.next = other_first; - other_first->prev = &head_; - - // Reset the other list - other.head_.init(); - } - - /** - * @brief Splices all elements from another list to the back of this list. - * - * Moves all elements from `other` to the end of `this` list in O(1) - * time. The `other` list becomes empty after the operation. - * - * @param other The list to splice from. - */ - void splice_tail(List& other) { - if (other.empty()) { - return; - } - list_node* this_last = head_.prev; - list_node* other_first = other.head_.next; - list_node* other_last = other.head_.prev; - - // Link this's last to other's first - this_last->next = other_first; - other_first->prev = this_last; - - // Link other's last to this's head - other_last->next = &head_; - head_.prev = other_last; - - // Reset the other list - other.head_.init(); - } - - T* pop_front() { - if (empty()) { - return nullptr; - } - list_node* node = head_.next; - node->prev->next = node->next; - node->next->prev = node->prev; - node->init(); - return get_obj(node); - } - - T* pop_back() { - if (empty()) { - return nullptr; - } - list_node* node = head_.prev; - node->prev->next = node->next; - node->next->prev = node->prev; - node->init(); - return get_obj(node); - } - - void remove(T* obj) { - list_node* node = get_node(obj); - node->prev->next = node->next; - node->next->prev = node->prev; - node->init(); - } - - T* front() { - return empty() ? nullptr : get_obj(head_.next); - } - - const T* front() const { - return empty() ? nullptr : get_obj(head_.next); - } - - T* back() { - return empty() ? nullptr : get_obj(head_.prev); - } - - const T* back() const { - return empty() ? nullptr : get_obj(head_.prev); - } - - iterator begin() { return iterator(head_.next); } - iterator end() { return iterator(&head_); } - const_iterator begin() const { return const_iterator(head_.next); } - const_iterator end() const { return const_iterator(&head_); } - const_iterator cbegin() const { return const_iterator(head_.next); } - const_iterator cend() const { return const_iterator(&head_); } - -private: - list_node head_; -}; - -/* ======================================================================== - * Linux-compatible C-style list macros (for VFS subsystem) - * ======================================================================== */ - -using list_head = list_node; - -inline void list_init(list_node* head) { - head->prev = head; - head->next = head; -} - -inline bool list_empty(const list_node* head) { - return head->next == head; -} - -inline void __list_add(list_node* node, list_node* p, list_node* n) { - n->prev = node; - node->next = n; - node->prev = p; - p->next = node; -} - -inline void list_add(list_node* node, list_node* head) { - __list_add(node, head, head->next); -} - -inline void list_add_tail(list_node* node, list_node* head) { - __list_add(node, head->prev, head); -} - -inline void list_del(list_node* node) { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = nullptr; - node->prev = nullptr; -} - -inline void list_del_init(list_node* node) { - node->prev->next = node->next; - node->next->prev = node->prev; - list_init(node); -} - -#define list_entry(ptr, type, member) container_of(ptr, type, member) - -#define list_for_each(pos, head) \ - for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next) - -#define list_for_each_safe(pos, tmp, head) \ - for ((pos) = (head)->next, (tmp) = (pos)->next; \ - (pos) != (head); \ - (pos) = (tmp), (tmp) = (pos)->next) diff --git a/include/lume/lumeos.lds.h b/include/lume/lumeos.lds.h deleted file mode 100644 index 58d2f72..0000000 --- a/include/lume/lumeos.lds.h +++ /dev/null @@ -1,193 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -/* - * Common Linker Script Macros (Machine-Independent) - * - * Shared section definitions that every architecture must emit. - * Architecture-specific lumeos.lds.S files #include this header - * and use these macros to avoid duplicating common boilerplate. - * - * Modeled after Linux include/asm-generic/vmlinux.lds.h - * Reference: docs/specs/linker_and_entry.md - */ - -#ifndef _LUME_LUMEOS_LDS_H -#define _LUME_LUMEOS_LDS_H - -/* ===== Text Section: executable code ===== - * - * .init.text is merged into the main .text segment so PC-relative `la` - * from regular code can call __init helpers without a thunk. Linux - * keeps a separate .init.text only to reclaim the pages after boot — - * LumeOS doesn't yet reclaim, so the merge is harmless and avoids an - * extra PT_LOAD entry. */ -#define TEXT_SECTION \ - .text : AT(ADDR(.text) - PAGE_OFFSET) { \ - _stext = .; \ - *(.text .text.*) \ - *(.init.text .init.text.*) \ - *(.fixup) \ - _etext = .; \ - } = 0 - -/* ===== Read-Only Data + C++ init_array + initramfs ===== - * - * Layout invariants: - * - extable / init_array / driver_array / initramfs all live INSIDE - * .rodata between _srodata and _erodata so the VMM has one R-only - * mapping to manage. - * - The relocation table (.lume.reloc) is NOT in here — it lives in - * its own padded output section (see RELOC_SECTION) so that its - * two-pass-build size variance can't shift downstream offsets. - * (Putting it in .rodata caused a heisenbug where pre-link offsets - * used by gen_reloc.py didn't match post-link offsets after the - * reloc.o blob was inserted.) - */ -#define RODATA_SECTION \ - .rodata : AT(ADDR(.rodata) - PAGE_OFFSET) { \ - _srodata = .; \ - *(.rodata .rodata.*) \ - *(.srodata .srodata.* .srodata.cst*) \ - . = ALIGN(8); \ - __extable_start = .; \ - KEEP(*(.extable)) \ - __extable_end = .; \ - INIT_ARRAY \ - DRIVER_ARRAY \ - /* Embedded initramfs CPIO archive */ \ - . = ALIGN(8); \ - __initramfs_start = .; \ - KEEP(*(.init.ramfs)) \ - __initramfs_end = .; \ - . = ALIGN(4096); \ - _erodata = .; \ - } - -/* ===== .rel.dyn / .rela.dyn — Linker-emitted RELA relocations ===== - * - * Mirrors arch/riscv/kernel/vmlinux.lds.S §101-109: the .rela.dyn - * section sits BETWEEN init data and .rodata so it lands in a - * read-only PT_LOAD segment alongside .text/.rodata. The companion - * dynamic-linker bookkeeping (.dynamic, .dynsym, .dynstr, .hash, - * .gnu.hash) lives in the RW segment AFTER .data — Linux does the - * same under #ifdef CONFIG_RELOCATABLE (§139-147). */ -#define RELA_DYN_SECTION \ - .rel.dyn : AT(ADDR(.rel.dyn) - PAGE_OFFSET) { \ - *(.rel.dyn*) \ - } \ - .rela.dyn : AT(ADDR(.rela.dyn) - PAGE_OFFSET) ALIGN(8) {\ - __rela_dyn_start = .; \ - *(.rela .rela*) \ - __rela_dyn_end = .; \ - } - -/* ===== GOT — kept; everything else dynamic-linker is discarded ===== - * - * Strict mirror of arch/riscv/kernel/vmlinux.lds.S in Linux: the only - * dynamic-linker artefact the kernel keeps is `.got` (it's referenced - * by every -fPIE compiled global access). `.plt .dynamic .dynsym - * .dynstr .hash .gnu.hash .interp .dynbss` are all sent to /DISCARD/ - * via the DISCARDS macro below — the kernel never invokes a dynamic - * linker (head.S walks .rela.dyn directly). - * - * Keeping .plt was the cause of two distinct bugs: - * 1. PLT trampoline target for an undefined symbol (selftest_reloc - * after we removed test_reloc.cc) was unresolved → jumps to a - * slot that re-jumps to itself → instruction page fault. - * 2. .plt carries X permission; living in the same PT_LOAD as .data - * forces the load segment to RWX, which `ld` warns about. - * - * Sit in the same PT_LOAD as .data because .got is RW. */ -#define GOT_SECTION \ - .got : AT(ADDR(.got) - PAGE_OFFSET) { *(.got*) } - -/* ===== Embedded initramfs (CPIO archive) ===== */ -#define INITRAMFS_SECTION \ - .init.ramfs : AT(ADDR(.init.ramfs) - PAGE_OFFSET) { \ - . = ALIGN(8); \ - __initramfs_start = .; \ - KEEP(*(.init.ramfs)) \ - __initramfs_end = .; \ - } - -/* ===== C++ Global Constructor Table ===== */ -#define INIT_ARRAY \ - . = ALIGN(8); \ - __init_array_start = .; \ - KEEP(*(.init_array .init_array.*)) \ - __init_array_end = .; - -/* ===== Driver Registration Table ===== */ -#define DRIVER_ARRAY \ - . = ALIGN(8); \ - PROVIDE(__drivers_start = .); \ - KEEP(*(.drivers)) \ - PROVIDE(__drivers_end = .); - -/* ===== Initialized Read-Write Data ===== - * - * .init.data is merged into .data for the same reason TEXT_SECTION - * absorbs .init.text — LumeOS doesn't yet reclaim __init pages, so - * splitting them gains nothing while costing a PT_LOAD entry. */ -#define DATA_SECTION \ - .data : AT(ADDR(.data) - PAGE_OFFSET) { \ - _sdata = .; \ - *(.data .data.*) \ - *(.init.data .init.data.*) \ - ARCH_DATA_EXTRA \ - _edata = .; \ - } - -/* ===== BSS: Uninitialized Data ===== */ -#define BSS_SECTION \ - .bss : AT(ADDR(.bss) - PAGE_OFFSET) { \ - _sbss = .; \ - *(.bss .bss.*) \ - *(.sbss .sbss.*) \ - ARCH_BSS_EXTRA \ - _ebss = .; \ - } - -/* ===== Discard Unwanted Sections ===== - * - * Mirrors arch/riscv/kernel/vmlinux.lds.S in Linux: - * /DISCARD/ : { - * *(.dynbss) - * *(.dynstr*) - * *(.dynamic*) - * *(.plt*) - * *(.interp*) - * *(.eh_frame) - * *(.note.GNU-stack) - * } - * - * Why each is safe to discard: - * .plt — -Bsymbolic resolves all internal refs at link time; - * any remaining PLT entry is an undefined symbol that - * the kernel would have crashed on anyway. - * .dynamic etc. — kernel doesn't invoke a dynamic linker; head.S - * walks __rela_dyn_start..__rela_dyn_end manually. - * .interp — no PT_INTERP at runtime. - * .eh_frame* — no C++ exceptions in kernel (-fno-exceptions). - * .note.* — boot-time identification metadata, unused. */ -#define DISCARDS \ - /DISCARD/ : { \ - *(.dynbss) \ - *(.dynstr*) \ - *(.dynamic*) \ - *(.dynsym*) \ - *(.hash*) *(.gnu.hash*) \ - *(.plt*) \ - *(.interp*) \ - *(.eh_frame .eh_frame_hdr) \ - *(.note .note.*) \ - *(.comment) \ - } - -/* ===== Kernel Image Boundary ===== */ -#define KERNEL_END \ - . = ALIGN(4096); \ - _kernel_end = .; - -#endif /* _LUME_LUMEOS_LDS_H */ diff --git a/include/lume/memblock.h b/include/lume/memblock.h deleted file mode 100644 index cb9a76b..0000000 --- a/include/lume/memblock.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * memblock — Boot-time physical memory allocator - * - * A simple region-based allocator active from early boot until - * the buddy system (PMM) takes over. Inspired by Linux's memblock. - * - * Lifetime: - * 1. memblock_init() — discovers RAM via FDT, reserves kernel image - * 2. vmm_init() — uses memblock_alloc for page table pages & page_map - * 3. pmm_init() — absorbs remaining free regions into buddy - * 4. memblock_retire() — marks memblock inactive; all alloc via PMM - * - * This eliminates the need for post-init pointer relocation when - * rebinding page_map to a VMEMMAP virtual address. - */ - -#include <lume/types.h> - -inline constexpr int kMemblockMaxRegions = 128; - -/* Initialize memblock: scan FDT for RAM, reserve kernel image + firmware. */ -void memblock_init(uint64 fdt_paddr); - -/* Mark a physical range as reserved (will not be handed to buddy). */ -void memblock_reserve(uint64 base, uint64 size); - -/* Allocate `size` bytes aligned to `align` from top of free memory. - * Returns PA, or 0 on failure. Used for page_map. */ -uint64 memblock_alloc_top(uint64 size, uint64 align); - -/* Allocate `size` bytes aligned to `align` from bottom of free memory. - * Returns PA, or 0 on failure. Used for page table pages. */ -uint64 memblock_alloc(uint64 size, uint64 align); - -/* Query memory layout (same info as FDT). */ -uint64 memblock_get_mem_base(); -uint64 memblock_get_mem_size(); - -/* Is memblock still the active allocator? */ -bool memblock_is_active(); - -/* Mark memblock as retired (PMM takes over). */ -void memblock_retire(); - -/* Iterate all free (unreserved) regions in ascending order. - * Used by pmm_init() to feed free pages into the buddy system. */ -void memblock_for_each_free(void (*cb)(uint64 base, uint64 size, void* ctx), - void* ctx); diff --git a/include/lume/mm_layout.h b/include/lume/mm_layout.h deleted file mode 100644 index 7744de0..0000000 --- a/include/lume/mm_layout.h +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * mm_layout.h — User/Kernel address space boundary definitions - * - * Single source of truth for the user/kernel VA split. - * All modules (VMM, uaccess, page fault, tests) MUST include this - * header instead of defining their own constants. - * - * Layout (SV39, RISC-V): - * [0x0000_0000_0000, kUserVaLimit) — User space - * [kUserVaLimit, 0xFFFF_FFFF_FFFF) — Kernel space (direct map, vmemmap, etc.) - * - * Reference: docs/specs/linux_abi_mm_plan.md §5 - */ - -#include <lume/types.h> -#include <lume/config.h> - -/* User VA range: [kUserVaBase, kUserVaLimit) - * kUserVaBase avoids mapping the null page (catch NULL derefs). - * - * SV39: user space is the lower half [0, 2^38). The upper half - * [0xFFFFFFC000000000, 0xFFFFFFFFFFFFFFFF] is kernel space. - * Addresses between 2^38 and 0xFFFFFFC000000000 are non-canonical - * and will always fault — they must never be used. - * - * This value MUST match the page table mode selected by the MD layer. - * If we ever support SV48/SV57, update this accordingly. */ -inline constexpr uint64 kUserVaBase = kPageSize; -inline constexpr uint64 kUserVaLimit = 0x4000000000ULL; /* 2^38 = 256 GB */ - -/* Kernel VA starts at the sign-extended upper half */ -inline constexpr uint64 kKernelVaBase = 0xFFFFFFC000000000ULL; - -/* User stack: sits at the top of the user VA range. - * Matches Linux STACK_TOP = TASK_SIZE = kUserVaLimit. - * One guard page below the top, 8 MB stack. */ -inline constexpr uint64 kUserStackSize = 8ULL * 1024 * 1024; -inline constexpr uint64 kUserStackTop = kUserVaLimit - kPageSize; /* guard page */ -inline constexpr uint64 kUserStackBase = kUserStackTop - kUserStackSize; - -/* - * Check whether an address range [addr, addr+len) is entirely - * within user space. Returns true if valid. - */ -inline bool is_user_range(uint64 addr, uint64 len) -{ - if (addr < kUserVaBase) { - return false; - } - if (addr >= kUserVaLimit) { - return false; - } - if (addr + len < addr) { - return false; // Overflow - } - if (addr + len > kUserVaLimit) { - return false; - } - return true; -} - -/* - * Check whether a single address is in user space. - */ -inline bool is_user_address(uint64 addr) -{ - return addr >= kUserVaBase && addr < kUserVaLimit; -} diff --git a/include/lume/mman.h b/include/lume/mman.h deleted file mode 100644 index d952419..0000000 --- a/include/lume/mman.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * POSIX Memory Management Constants - * Reference: docs/specs/syscall.md §9 - */ - -/* mmap / mprotect protection flags */ -inline constexpr int PROT_NONE = 0x0; -inline constexpr int PROT_READ = 0x1; -inline constexpr int PROT_WRITE = 0x2; -inline constexpr int PROT_EXEC = 0x4; - -/* mmap flags */ -inline constexpr int MAP_SHARED = 0x01; -inline constexpr int MAP_PRIVATE = 0x02; -inline constexpr int MAP_FIXED = 0x10; -inline constexpr int MAP_ANONYMOUS = 0x20; diff --git a/include/lume/mount.h b/include/lume/mount.h deleted file mode 100644 index 13f8e62..0000000 --- a/include/lume/mount.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * mount.h — Internal mount structure - */ - -#include <lume/types.h> -#include <lume/list.h> -#include <lume/atomic.h> -#include <lume/file.h> - -struct dentry; -struct super_block; -struct file_system_type; - -/* ================================================================== */ -/* mount (VFS-internal) */ -/* ================================================================== */ - -struct mount { - vfsmount mnt; - mount* mnt_parent; - dentry* mnt_mountpoint; - list_node mnt_child; - list_head mnt_mounts; - list_node mnt_list; - lume::atomic<int32> mnt_count; -}; - -inline mount* real_mount(vfsmount* m) { - return reinterpret_cast<mount*>(m); -} - -/* ================================================================== */ -/* Mount API */ -/* ================================================================== */ - -int do_mount(const char* dev, const char* dir, - const char* fstype, uint64 flags, void* data); -int do_umount(vfsmount* mnt, int flags); - -vfsmount* vfs_kern_mount(file_system_type* type, int flags, - const char* name, void* data); - -/* Global root */ -extern vfsmount* g_root_mnt; -extern dentry* g_root_dentry; - -void mount_init(); diff --git a/include/lume/mutex.h b/include/lume/mutex.h deleted file mode 100644 index 9719aa6..0000000 --- a/include/lume/mutex.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Mutex — Linux-style sleeping mutex (no priority inheritance). - * - * Semantics mirror Linux kernel/locking/mutex.c: - * - Single owner (nullptr when free). - * - FIFO wait list — first waiter is the next owner. - * - Recursive acquire by the same task is FORBIDDEN (panic). - * - Owner MUST be the one to unlock. - * - lock() may sleep; MUST NOT be called from IRQ context, with - * preemption disabled, or while holding a spinlock. - * - try_lock() never sleeps; may be called from any context. - * - * Priority inheritance lives in a separate primitive (RtMutex, future) - * just like Linux splits struct mutex / struct rt_mutex. - * - * Reference: docs/specs/mutex.md - */ - -#include <lume/types.h> -#include <lume/list.h> -#include <kernel/sync/spinlock.h> - -struct TaskControlBlock; - -class Mutex { -public: - void init(const char* name); - - /* Blocking acquire (uninterruptible). */ - void lock(); - - /* Non-blocking attempt. Returns true if acquired. */ - bool try_lock(); - - /* Release; only the owner may call (else panic). */ - void unlock(); - - bool is_locked() const { return owner_ != nullptr; } - bool is_owned_by_current() const; - TaskControlBlock* owner() const { return owner_; } - -private: - TaskControlBlock* owner_ = nullptr; - Spinlock wait_lock_; - list_node wait_list_{}; - const char* name_ = nullptr; -}; - -/* RAII guard. */ -class MutexGuard { -public: - explicit MutexGuard(Mutex& m) : m_(m) { m_.lock(); } - ~MutexGuard() { m_.unlock(); } - MutexGuard(const MutexGuard&) = delete; - MutexGuard& operator=(const MutexGuard&) = delete; -private: - Mutex& m_; -}; diff --git a/include/lume/namei.h b/include/lume/namei.h deleted file mode 100644 index 1764693..0000000 --- a/include/lume/namei.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * namei.h — Pathname lookup (path resolution) - */ - -#include <lume/types.h> -#include <lume/file.h> /* struct path */ -#include <lume/dcache.h> /* struct qstr */ - -/* ================================================================== */ -/* LOOKUP_* flags */ -/* ================================================================== */ - -inline constexpr uint32 LOOKUP_FOLLOW = 0x0001; -inline constexpr uint32 LOOKUP_DIRECTORY = 0x0002; -inline constexpr uint32 LOOKUP_CREATE = 0x0200; -inline constexpr uint32 LOOKUP_EXCL = 0x0400; -inline constexpr uint32 LOOKUP_PARENT = 0x0010; - -/* ================================================================== */ -/* Path lookup API */ -/* ================================================================== */ - -int kern_path(const char* name, unsigned int flags, path* result); -int filename_lookup(int dfd, const char* name, unsigned int flags, path* result); -dentry* lookup_one_len(const char* name, dentry* parent, int len); - -void namei_init(); diff --git a/include/lume/new.h b/include/lume/new.h deleted file mode 100644 index cdcacb8..0000000 --- a/include/lume/new.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Placement New for Freestanding Environments - * - * In -ffreestanding -nostdlib mode, <new> may not be available. - * LumeOS provides its own placement new/delete operators. - * - * Usage: g_obj = new (g_obj_buf) MyClass(args...); - * - * Reference: docs/specs/global_init.md §3.1 - */ - -inline void* operator new(decltype(sizeof(0)), void* ptr) noexcept { return ptr; } -inline void operator delete(void*, void*) noexcept {} diff --git a/include/lume/page.h b/include/lume/page.h deleted file mode 100644 index 61bff95..0000000 --- a/include/lume/page.h +++ /dev/null @@ -1,151 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Page — Physical page descriptor - * - * Each Page describes one 4KB physical page. A flat array of Page - * structs (page_map) covers all physical memory discovered via FDT. - * - * Memory layout is compressed using a union: only one of free/slab - * metadata is valid at a time, determined by `type`. - * - * Fields: - * refcount — lifecycle reference count (atomic). Page cannot be - * freed while refcount > 0. - * mapcount — PTE mapping count (atomic). Number of page table - * entries pointing to this page. Used by COW and - * future reclaim. - * flags — page state bits (PG_*). Also serves as a bit-lock - * via PG_LOCKED for short critical sections. - * type — discriminant for the union (Free/Slab/Anon/File). - * mapping — pointer to reverse-mapping context. For anonymous - * pages, points to AnonVma (low bit set). For file - * pages, points to FileMapping (low bit clear). - * index — page offset within the mapping object. - * - * Reference: docs/specs/pmm.md §3.1 - */ - -#include <lume/types.h> -#include <lume/list.h> -#include <lume/atomic.h> - -/* Forward declarations */ -class KmemCache; - -/* ================================================================== */ -/* Page type discriminant */ -/* ================================================================== */ - -enum class PageType : uint8 { - Free, // In Buddy free list - PcpCached, // In Per-CPU cache (invisible to buddy coalescing) - Allocated, // Handed out but not yet typed (PMM default) - Slab, // Backing a Slab cache - Anon, // Anonymous user page - File, // File-backed page (page cache) -}; - -/* ================================================================== */ -/* Page flags (stored as atomic uint32) */ -/* ================================================================== */ - -inline constexpr uint32 kPgLocked = (1U << 0); // Bit-lock for short critical sections -inline constexpr uint32 kPgReferenced = (1U << 1); // Accessed since last check -inline constexpr uint32 kPgDirty = (1U << 2); // Modified, needs writeback -inline constexpr uint32 kPgWriteback = (1U << 3); // IO writeback in progress -inline constexpr uint32 kPgLru = (1U << 4); // On an LRU list -inline constexpr uint32 kPgMapped = (1U << 5); // Has at least one PTE mapping -inline constexpr uint32 kPgSwapcache = (1U << 6); // In swap cache (future) -inline constexpr uint32 kPgCow = (1U << 7); // Involved in COW sharing - -/* ================================================================== */ -/* Page descriptor */ -/* ================================================================== */ - -struct Page { - /* --- Counts (atomic, lock-free) --- */ - lume::atomic<uint32> refcount; // Lifecycle ref: 0 = reclaimable - lume::atomic<uint32> mapcount; // PTE mapping count: 0 = no user mapping - - /* --- State --- */ - lume::atomic<uint32> flags; // PG_* bits (also serves as bit-lock) - PageType type; // Discriminant for union - uint8 order; // Buddy order (0–10, i.e. 4KB–4MB) - - /* --- Reverse mapping --- */ - void* mapping; // AnonVma* (low bit set) or FileMapping* - uint64 index; // Page offset within mapping object - - /* --- LRU (future) --- */ - list_node lru; // LRU list linkage (for reclaim) - - /* --- Subsystem-specific metadata --- */ - union { - /* Valid when type == Free */ - struct { - list_node free_link; // Link into Buddy or PCP free list - } free; - - /* Valid when type == Slab */ - struct { - KmemCache* cache; // Owning slab cache - uint32 obj_count; // Number of allocated objects on this page - void* freelist; // Head of in-page free object linked list - } slab; - - /* type == Anon / File: no extra union metadata (rmap via mapping) */ - }; -}; - -/* ================================================================== */ -/* Page bit-lock (lightweight, no sleep, used for rmap critical */ -/* sections and short metadata updates) */ -/* ================================================================== */ - -inline bool page_trylock(Page* page) -{ - uint32 old = page->flags.fetch_or(kPgLocked); - return (old & kPgLocked) == 0; -} - -inline void page_lock(Page* page) -{ - while (!page_trylock(page)) { - /* spin — acceptable for short critical sections only */ - } -} - -inline void page_unlock(Page* page) -{ - page->flags.fetch_and(~kPgLocked); -} - -/* ================================================================== */ -/* Mapping pointer helpers (Linux convention: low bit = anon) */ -/* ================================================================== */ - -inline bool page_is_anon(const Page* page) -{ - return (reinterpret_cast<uint64>(page->mapping) & 1ULL) != 0; -} - -inline void* page_mapping_raw(const Page* page) -{ - return reinterpret_cast<void*>( - reinterpret_cast<uint64>(page->mapping) & ~1ULL); -} - -inline void page_set_anon_mapping(Page* page, void* anon_vma) -{ - page->mapping = reinterpret_cast<void*>( - reinterpret_cast<uint64>(anon_vma) | 1ULL); -} - -inline void page_set_file_mapping(Page* page, void* file_mapping) -{ - page->mapping = file_mapping; -} diff --git a/include/lume/page_cache.h b/include/lume/page_cache.h deleted file mode 100644 index abdc535..0000000 --- a/include/lume/page_cache.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * page_cache.h — Page Cache interface - * - * Provides a stable abstraction for caching physical pages indexed by - * (mapping, index) pairs. All file-backed fault paths should go - * through this interface so that upgrading the backing implementation - * (e.g. LRU eviction, writeback, radix tree) does not require - * changing any caller. - * - * Current implementation: simple open-addressing hash table. - * Future: radix tree + LRU lists + writeback integration. - * - * Terminology: - * mapping — opaque pointer identifying the backing object - * (FileMapping*, or any future cache-able object). - * index — page-granularity offset within the mapping. - * - * Reference: docs/specs/linux_abi_mm_plan.md §2.9, §3 - */ - -#include <lume/types.h> - -struct Page; - -/* - * Look up a cached page by (mapping, index). - * Returns the Page* if found (with refcount incremented), or nullptr. - * Caller must call page_cache_put() when done. - */ -Page* page_cache_get(void* mapping, uint64 index); - -/* - * Insert a page into the cache, associated with (mapping, index). - * The page's refcount is incremented by the cache. - * If a page already exists at (mapping, index), returns -EEXIST. - * Returns 0 on success, negative errno on failure. - */ -int page_cache_insert(void* mapping, uint64 index, Page* page); - -/* - * Release a reference obtained via page_cache_get(). - * This decrements the page's refcount. If the page was removed - * from the cache and refcount drops to 0, the page is freed. - */ -void page_cache_put(Page* page); - -/* - * Remove a page from the cache by (mapping, index). - * Decrements the cache's reference on the page. - * Returns the removed Page* (caller does NOT own a new ref), - * or nullptr if not found. - */ -Page* page_cache_remove(void* mapping, uint64 index); - -/* - * Remove all pages associated with a given mapping. - * Used during file close / inode eviction / truncate. - * Each removed page has its cache reference decremented. - */ -void page_cache_invalidate(void* mapping); - -/* - * Look up a page; if not found, allocate one, insert it, and return it. - * The returned page has its refcount incremented (caller must put). - * Returns nullptr on OOM. - * - * This is the primary interface for file-backed fault paths: - * the caller gets a page and then fills it with file data if kPgUptodate - * is not set. - */ -Page* page_cache_get_or_alloc(void* mapping, uint64 index); - -/* - * Initialize the page cache subsystem. - * Called once during boot after slab_init(). - */ -void page_cache_init(); diff --git a/include/lume/pgrp.h b/include/lume/pgrp.h deleted file mode 100644 index 127f3f8..0000000 --- a/include/lume/pgrp.h +++ /dev/null @@ -1,125 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Process Group / Session infrastructure. - * - * Linux models pgrp/session via struct pid + PIDTYPE_PGID/PIDTYPE_SID hlists. - * We use a simpler design that supports the same operations cheaply: - * - * - Each thread group owns one signal_struct (refcount-shared with - * CLONE_THREAD siblings). - * - signal_struct carries pgid/sid and is the linked-list node on a - * fixed-size pgrp hash table. - * - kill(pid<=0), tty_signal_pgrp, orphan checks all walk one bucket. - * - * Concurrency: g_pgrp_lock protects every bucket and the pgrp_link of - * every signal_struct on a bucket. signal_struct::lock is a finer-grain - * lock for fields that change without re-hashing (e.g. tty pointer). - * - * Reference: Linux include/linux/pid.h, kernel/pid.c - */ - -#include <lume/types.h> -#include <lume/list.h> -#include <kernel/sync/spinlock.h> - -struct signal_struct; -struct TaskControlBlock; - -/* ================================================================== */ -/* Subsystem init */ -/* ================================================================== */ - -void pgrp_init(); - -/* ================================================================== */ -/* signal_struct lifecycle */ -/* ================================================================== */ - -/* - * Allocate a new signal_struct for `leader`, with sid=pgid=leader_pid, - * refcount=1, attached to pgrp `leader_pid`. Returns nullptr on OOM. - */ -signal_struct* alloc_signal_struct(int32 leader_pid, - TaskControlBlock* leader); - -/* - * Allocate a child signal_struct inheriting pgid/sid/tty from `parent`. - * The new struct is attached to the parent's pgrp and starts with - * refcount=1. Used by fork (non-CLONE_THREAD). - */ -signal_struct* fork_signal_struct(signal_struct* parent, - TaskControlBlock* child_leader); - -/* Increment refcount (CLONE_THREAD share). */ -void get_signal_struct(signal_struct* sig); - -/* - * Decrement refcount; on last drop, detach from pgrp hash and free. - * Pass the task that's dropping the reference so we can manage - * leader pointers if the leader exits while sub-threads remain. - */ -void put_signal_struct(signal_struct* sig); - -/* ================================================================== */ -/* Pgrp operations (assume signal_struct is allocated) */ -/* ================================================================== */ - -/* - * Move a signal_struct from its current pgrp to `new_pgid`. - * Used by setpgid / setsid. Takes g_pgrp_lock internally. - */ -void change_pgid(signal_struct* sig, int32 new_pgid); - -/* - * Invoke `fn(sig)` for every signal_struct whose pgid == target. - * Holds g_pgrp_lock for the entire walk — fn must not block, sleep, - * or take locks that order before g_pgrp_lock. - * - * Template-y but kept in header to avoid a function-ptr indirection; - * keep callsites lean. - */ -template <typename F> -void for_each_pgrp_member(int32 target_pgid, F&& fn); - -/* - * Count the number of signal_structs in `pgid`. Used by setsid - * preflight (can't create a session if you're already a pgrp leader - * with members) and orphan checks. - */ -int pgrp_member_count(int32 pgid); - -/* ================================================================== */ -/* Implementation details exposed for the template above */ -/* ================================================================== */ - -constexpr int kPgrpHashShift = 6; -constexpr int kPgrpHashSize = 1 << kPgrpHashShift; /* 64 buckets */ -constexpr int kPgrpHashMask = kPgrpHashSize - 1; - -extern list_node g_pgrp_hash[kPgrpHashSize]; -extern Spinlock g_pgrp_lock; - -inline int pgrp_hash_idx(int32 pgid) { - return static_cast<int>(static_cast<uint32>(pgid)) & kPgrpHashMask; -} - -#include <lume/signal_types.h> - -template <typename F> -void for_each_pgrp_member(int32 target_pgid, F&& fn) -{ - LockGuard guard(g_pgrp_lock); - list_node* bucket = &g_pgrp_hash[pgrp_hash_idx(target_pgid)]; - list_node* node = bucket->next; - while (node != bucket) { - list_node* nxt = node->next; /* fn may not unlink, but be safe */ - auto* sig = list_entry<signal_struct, &signal_struct::pgrp_link>(node); - if (sig->pgid == target_pgid) - fn(sig); - node = nxt; - } -} diff --git a/include/lume/pgtable_types.h b/include/lume/pgtable_types.h deleted file mode 100644 index e309a82..0000000 --- a/include/lume/pgtable_types.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Page Table Entry Types — strongly typed wrappers. - * - * Layout and macro names mirror Linux's arch/riscv/include/asm/page.h - * and pgtable-64.h so that arch/riscv/mm/init.c can be copied from - * Linux without source edits. The wrapped struct prevents accidental - * mixing of a pte_t with a pgd_t or a raw physical address, which the - * previous bare-uint64 design in pmap.cc could not catch. - * - * Underlying width on RV64 LP64 is `unsigned long` = 64 bits, matching - * Linux exactly — assembly references (e.g. REG_S/REG_L on a pte_t*) - * see the same byte layout. - * - * SV39 uses 3 levels (pgd -> pmd -> pte); SV48 uses 4 (pgd -> pud -> - * pmd -> pte). p4d_t/pud_t are emitted unconditionally so that the - * higher-level abstractions in asm-generic/pgtable-nopud.h and friends - * (which Linux uses to collapse unused levels) work without #ifdef. - */ - -#include <lume/types.h> - -typedef struct { - unsigned long pte; -} pte_t; - -typedef struct { - unsigned long pmd; -} pmd_t; - -typedef struct { - unsigned long pud; -} pud_t; - -typedef struct { - unsigned long p4d; -} p4d_t; - -typedef struct { - unsigned long pgd; -} pgd_t; - -typedef struct { - unsigned long pgprot; -} pgprot_t; - -typedef struct page *pgtable_t; - -/* Field accessors */ -#define pte_val(x) ((x).pte) -#define pmd_val(x) ((x).pmd) -#define pud_val(x) ((x).pud) -#define p4d_val(x) ((x).p4d) -#define pgd_val(x) ((x).pgd) -#define pgprot_val(x) ((x).pgprot) - -/* Constructors (cast raw uint64 to wrapped type) */ -#define __pte(x) ((pte_t) { (x) }) -#define __pmd(x) ((pmd_t) { (x) }) -#define __pud(x) ((pud_t) { (x) }) -#define __p4d(x) ((p4d_t) { (x) }) -#define __pgd(x) ((pgd_t) { (x) }) -#define __pgprot(x) ((pgprot_t) { (x) }) - -#define PTE_FMT "%016lx" diff --git a/include/lume/pid.h b/include/lume/pid.h deleted file mode 100644 index 8503750..0000000 --- a/include/lume/pid.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * PID Allocator — Bitmap-based O(1) block search - * Reference: docs/specs/task.md §3.2 - */ - -#include <lume/types.h> -#include <kernel/sync/spinlock.h> - -inline constexpr int32 kMaxPid = 32768; - -class PidAllocator { -public: - void init(); - int32 alloc(); - void free(int32 pid); - -private: - static constexpr int32 kBitmapWords = kMaxPid / 64; - Spinlock lock_; - uint64 bitmap_[kBitmapWords]; - int32 next_hint_ = 2; -}; - -extern PidAllocator g_pid_alloc; diff --git a/include/lume/pipe.h b/include/lume/pipe.h deleted file mode 100644 index c905c9a..0000000 --- a/include/lume/pipe.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * pipe.h — Pipe data structure and API - * - * A pipe is a unidirectional byte stream backed by a fixed-size - * circular buffer. Two file structs (reader + writer) share a - * single pipe_inode_info. - */ - -#include <lume/types.h> -#include <lume/atomic.h> -#include <lume/waitqueue.h> -#include <kernel/sync/spinlock.h> - -struct file; -struct files_struct; - -/* ================================================================== */ -/* pipe_inode_info */ -/* ================================================================== */ - -inline constexpr int PIPE_BUF_SIZE = 4096; - -struct pipe_inode_info { - char buf[PIPE_BUF_SIZE]; - int rd_pos; /* Read position in circular buffer */ - int wr_pos; /* Write position in circular buffer */ - int len; /* Bytes currently in buffer */ - Spinlock lock; - WaitQueue rd_wait; /* Readers sleep here when empty */ - WaitQueue wr_wait; /* Writers sleep here when full */ - - lume::atomic<int32> readers; /* Number of open read ends */ - lume::atomic<int32> writers; /* Number of open write ends */ - lume::atomic<int32> refcount; /* Total references */ -}; - -/* ================================================================== */ -/* API */ -/* ================================================================== */ - -/* Create a pipe, install read/write fds into the given files_struct. - * Returns 0 on success, negative errno on failure. */ -int do_pipe2(files_struct* files, int fds[2], int flags); - -/* Allocate a fresh pipe_inode_info */ -pipe_inode_info* alloc_pipe_info(); -void free_pipe_info(pipe_inode_info* pipe); diff --git a/include/lume/platform_device.h b/include/lume/platform_device.h deleted file mode 100644 index ac3e527..0000000 --- a/include/lume/platform_device.h +++ /dev/null @@ -1,64 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * platform_device / platform_driver — FDT-described memory-mapped devices. - * - * Mirrors Linux include/linux/platform_device.h. The platform bus is - * the catch-all bus for devices that don't live on a real bus like PCI - * or USB — every device discovered via the FDT lands here. - * - * Reference: docs/specs/storage_stack.md §4.3 - */ - -#include <lume/types.h> -#include <lume/device.h> - -class DeviceNode; - -/* Compatible-string -> driver-private data table (Linux's of_device_id). */ -struct of_device_id { - const char* compatible; - const void* data; -}; - -struct platform_device { - device dev; - DeviceNode* of_node; // FDT node this device came from - uint64 mmio_base; // first `reg` cell from FDT (0 if none) - uint64 mmio_size; // second `reg` cell (0 if none) - int irq; // first interrupt (-1 if none / not parsed) -}; - -struct platform_driver { - device_driver driver; - int (*probe)(platform_device*); - void (*remove)(platform_device*); - const of_device_id* of_match_table; // NULL-terminated array -}; - -extern bus_type platform_bus; - -void platform_bus_init(); -int platform_driver_register(platform_driver* drv); -int platform_device_register(platform_device* pdev); - -/* Helper: pull current driver out of a probed device. */ -inline platform_driver* to_platform_driver(device_driver* drv) -{ - return container_of(drv, platform_driver, driver); -} -inline platform_device* to_platform_device(device* dev) -{ - return container_of(dev, platform_device, dev); -} - -/* Linker-set registration macro — drop a pointer to your platform_driver - * into the .drivers section. driver_probe_all() iterates this set at - * boot. Use a unique token in CONCAT to avoid name collisions. */ -#define PLATFORM_DRIVER(_drv) \ - extern platform_driver _drv; \ - static platform_driver* const __pdrv_ptr_##_drv \ - __attribute__((used, section(".drivers"))) = &_drv diff --git a/include/lume/pmm.h b/include/lume/pmm.h deleted file mode 100644 index 3e4b819..0000000 --- a/include/lume/pmm.h +++ /dev/null @@ -1,108 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Physical Memory Manager (PMM) — Buddy System + Per-CPU Cache - * - * Manages all physical pages discovered via FDT. Built on a - * power-of-two buddy allocator for multi-page requests, with a - * Per-CPU single-page cache (PCP) to reduce lock contention on the - * hot single-page alloc/free path. - * - * Concurrency model: - * - PCP operations run with interrupts disabled (same-CPU safety). - * - Global buddy operations are protected by a single Spinlock. - * - Reference counts use __atomic builtins (lock-free). - * - * Reference: docs/specs/pmm.md - */ - -#include <lume/types.h> -#include <lume/page.h> -#include <lume/addr_types.h> -#include <lume/config.h> - -/* Buddy system constants */ -inline constexpr int kMaxOrder = CONFIG_MAX_ORDER; // Orders 0..(N-1) - -/* Per-CPU cache dynamic parameters (calculated in pmm_init) */ -extern uint32 g_pcp_high_watermark; -extern uint32 g_pcp_batch_size; - -/* ================================================================== */ -/* Public free-function API */ -/* ================================================================== */ - -/* - * Initialize the PMM. Called by BSP after vmm_init() + memblock. - * page_map is already mapped at VMEMMAP VA by vmm_init. - * Populates buddy lists from memblock's free regions, then retires memblock. - * Panics on failure. - */ -void pmm_init(); - -/* --- Single-page fast path (uses PCP) --- */ - -// Allocate one 4KB page. Returns nullptr on OOM. -Page* pmm_alloc_page(); - -// Free one 4KB page. -void pmm_free_page(Page* page); - -/* --- Multi-page slow path (direct buddy) --- */ - -// Allocate 2^order contiguous pages. Returns nullptr on OOM. -Page* pmm_alloc_pages(uint8 order); - -// Free 2^order contiguous pages. -void pmm_free_pages(Page* page, uint8 order); - -/* --- Reference counting (atomic, lock-free) --- */ - -void page_incref(Page* page); -void page_decref(Page* page); - -/* --- Map counting (atomic, lock-free) --- */ - -inline void page_inc_mapcount(Page* page) { - page->mapcount.fetch_add(1); -} - -inline uint32 page_dec_mapcount(Page* page) { - return page->mapcount.fetch_sub(1) - 1; // Returns new value -} - -inline uint32 page_mapcount(const Page* page) { - return page->mapcount.load(__ATOMIC_RELAXED); -} - -/* --- Address conversion --- */ - -// Convert a Page* to its physical address. -PhysAddr page_to_pa(const Page* page); - -// Convert a physical address to its Page*. -Page* pa_to_page(PhysAddr pa); - -// Convert a Page* to a kernel virtual address. -VirtAddr page_to_va(const Page* page); - -/* --- PFN (Page Frame Number) abstraction --- */ -/* - * PFN is the fundamental unit for PA↔Page conversion. - * PA↔PFN converters already exist in addr.h (pa_to_pfn / pfn_to_pa). - * When sparse vmemmap lands, only pfn_to_page/page_to_pfn - * need to change — no callers are affected. - */ - -// Convert PFN to Page*. PFN = pa / PAGE_SIZE. -Page* pfn_to_page(uint64 pfn); - -// Convert Page* to PFN. -uint64 page_to_pfn(const Page* page); - -// Query PMM memory range (for VMM kernel mapping) -PhysAddr pmm_get_mem_base(); -uint64 pmm_get_mem_size(); diff --git a/include/lume/poll.h b/include/lume/poll.h deleted file mode 100644 index 7d5bca2..0000000 --- a/include/lume/poll.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * poll.h — POSIX poll() / ppoll() infrastructure. - * - * Linux pattern (include/linux/poll.h): - * - file_operations->poll(file, poll_table) returns a bitmask of - * POLL* events that are currently true on this file. - * - As a side effect, the poll callback calls poll_wait(file, wq, pt) - * to register the caller on every wait queue that might fire when - * state changes. sys_ppoll() then sleeps on those queues until - * one of them fires or a signal/timeout arrives. - * - * Our minimal implementation supports a SINGLE wait queue per poll call - * (sufficient for nfds==1, which is the BusyBox interactive shell case). - * Multi-fd polls work but fall back to busy re-checking; a proper - * per-fd waiter-list upgrade can come later. - */ - -#include <lume/types.h> - -struct file; -class WaitQueue; - -/* ================================================================== */ -/* UAPI: pollfd struct + POLL* event bits (Linux asm-generic) */ -/* ================================================================== */ - -struct pollfd { - int32 fd; - int16 events; - int16 revents; -}; - -inline constexpr int16 POLLIN = 0x0001; -inline constexpr int16 POLLPRI = 0x0002; -inline constexpr int16 POLLOUT = 0x0004; -inline constexpr int16 POLLERR = 0x0008; -inline constexpr int16 POLLHUP = 0x0010; -inline constexpr int16 POLLNVAL = 0x0020; -inline constexpr int16 POLLRDNORM = 0x0040; -inline constexpr int16 POLLRDBAND = 0x0080; -inline constexpr int16 POLLWRNORM = 0x0100; -inline constexpr int16 POLLWRBAND = 0x0200; - -/* ================================================================== */ -/* Kernel-side poll_table */ -/* ================================================================== */ - -/* - * Carried into file_operations->poll(). Drivers call poll_wait() with - * the wait queue they'd like the poller to sleep on; we record the - * first one. When `wq == nullptr` on entry, no real registration is - * needed (the caller is just probing readiness). - */ -struct poll_table { - WaitQueue* wq; /* first wait queue registered (single-wq design) */ -}; - -/* - * Called from f_op->poll() implementations to register a wait queue. - * If `pt` is null we're in a probe-only pass — caller doesn't want to - * sleep, just to read current revents. - */ -void poll_wait(file* fp, WaitQueue* wq, poll_table* pt); diff --git a/include/lume/ptrace.h b/include/lume/ptrace.h deleted file mode 100644 index 687d103..0000000 --- a/include/lume/ptrace.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * PtRegs — Linux-compatible user register context - * - * This structure MUST match the Linux RISC-V pt_regs layout exactly. - * It is the canonical representation for: - * - Signal frame construction (ucontext / sigcontext) - * - ptrace(GETREGS/SETREGS) - * - /proc/<pid>/regs - * - * The internal TrapFrame (arch/trapframe.h) has a DIFFERENT layout - * optimized for fast trap entry/exit. Conversion between the two - * is done via trapframe_to_pt_regs() / pt_regs_to_trapframe(). - * - * Reference: Linux arch/riscv/include/asm/ptrace.h - */ - -#include <lume/types.h> - -struct PtRegs { - uint64 epc; // Program counter at trap - uint64 ra; // x1 - uint64 sp; // x2 - uint64 gp; // x3 - uint64 tp; // x4 - uint64 t0; // x5 - uint64 t1; // x6 - uint64 t2; // x7 - uint64 s0; // x8 - uint64 s1; // x9 - uint64 a0; // x10 - uint64 a1; // x11 - uint64 a2; // x12 - uint64 a3; // x13 - uint64 a4; // x14 - uint64 a5; // x15 - uint64 a6; // x16 - uint64 a7; // x17 - uint64 s2; // x18 - uint64 s3; // x19 - uint64 s4; // x20 - uint64 s5; // x21 - uint64 s6; // x22 - uint64 s7; // x23 - uint64 s8; // x24 - uint64 s9; // x25 - uint64 s10; // x26 - uint64 s11; // x27 - uint64 t3; // x28 - uint64 t4; // x29 - uint64 t5; // x30 - uint64 t6; // x31 - /* CSRs */ - uint64 status; // sstatus - uint64 badaddr; // stval - uint64 cause; // scause - /* Syscall bookkeeping */ - uint64 orig_a0; // a0 value before syscall (for restart) -}; - -static_assert(sizeof(PtRegs) == 36 * 8, "PtRegs must be 288 bytes (Linux ABI)"); - -/* - * Convert between internal TrapFrame and Linux-ABI PtRegs. - * These are the ONLY places that know both layouts. - * Future TrapFrame restructuring only needs to update these two functions. - */ -namespace arch { struct TrapFrame; } - -void trapframe_to_pt_regs(PtRegs* dst, const arch::TrapFrame* src, - uint64 scause, uint64 stval); -void pt_regs_to_trapframe(arch::TrapFrame* dst, const PtRegs* src); diff --git a/include/lume/random.h b/include/lume/random.h deleted file mode 100644 index 740b060..0000000 --- a/include/lume/random.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -#include <lume/types.h> - -enum class RandomSeedSource : uint8 { - Unknown = 0, - FdtProvided, - HwRandom, - CycleFallback, -}; - -/* - * MI: Machine-Independent Random Number Generator API - * - * Provides early PRNG and eventually a full CSPRNG. - */ - -/* - * Initialize early PRNG with a seed (e.g., from FDT). - * If seed is 0, attempts to use hardware TRNG or falls back to timer jitter. - */ -void random_early_init(uint64 seed); - -/* Consume random bits */ -uint64 get_random_u64(); -uint32 get_random_u32(); -void get_random_bytes(void* buf, size_t len); - -/* Inject entropy (for future interrupt/device mixing) */ -void add_device_randomness(const void* buf, size_t len); - -/* Early-seed metadata (for boot diagnostics/KASLR logs). */ -RandomSeedSource random_early_seed_source(); -uint64 random_early_seed_value(); -const char* random_seed_source_name(RandomSeedSource source); diff --git a/include/lume/rbtree.h b/include/lume/rbtree.h deleted file mode 100644 index 80b0c6c..0000000 --- a/include/lume/rbtree.h +++ /dev/null @@ -1,207 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Red-Black Trees — public API - * Adapted from Linux kernel include/linux/rbtree.h - * - * (C) 1999 Andrea Arcangeli <andrea@suse.de> - */ - -#pragma once - -#include <lume/compiler.h> -#include <lume/rbtree_types.h> -#include <lume/container_of.h> - -/* ------------------------------------------------------------------ */ -/* Core macros */ -/* ------------------------------------------------------------------ */ - -#define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3UL)) - -#define rb_entry(ptr, type, member) container_of(ptr, type, member) - -#define RB_EMPTY_ROOT(root) (READ_ONCE((root)->rb_node) == nullptr) - -#define RB_EMPTY_NODE(node) \ - ((node)->__rb_parent_color == (unsigned long)(node)) -#define RB_CLEAR_NODE(node) \ - ((node)->__rb_parent_color = (unsigned long)(node)) - -/* ------------------------------------------------------------------ */ -/* Core API (implemented in lib/rbtree.cc) */ -/* ------------------------------------------------------------------ */ - -#ifdef __cplusplus -extern "C" { -#endif - -void rb_insert_color(struct rb_node *, struct rb_root *); -void rb_erase(struct rb_node *, struct rb_root *); - -struct rb_node *rb_next(const struct rb_node *); -struct rb_node *rb_prev(const struct rb_node *); -struct rb_node *rb_first(const struct rb_root *); -struct rb_node *rb_last(const struct rb_root *); - -struct rb_node *rb_first_postorder(const struct rb_root *); -struct rb_node *rb_next_postorder(const struct rb_node *); - -void rb_replace_node(struct rb_node *victim, struct rb_node *_new, - struct rb_root *root); - -#ifdef __cplusplus -} -#endif - -/* ------------------------------------------------------------------ */ -/* Inline helpers */ -/* ------------------------------------------------------------------ */ - -static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, - struct rb_node **rb_link) -{ - node->__rb_parent_color = (unsigned long)parent; - node->rb_left = node->rb_right = nullptr; - *rb_link = node; -} - -#define rb_entry_safe(ptr, type, member) \ - ({ __typeof__(ptr) ____ptr = (ptr); \ - ____ptr ? rb_entry(____ptr, type, member) : nullptr; \ - }) - -/* ------------------------------------------------------------------ */ -/* Cached (leftmost) tree helpers */ -/* ------------------------------------------------------------------ */ - -#define rb_first_cached(root) (root)->rb_leftmost - -static inline void rb_insert_color_cached(struct rb_node *node, - struct rb_root_cached *root, - bool leftmost) -{ - if (leftmost) - root->rb_leftmost = node; - rb_insert_color(node, &root->rb_root); -} - -static inline void rb_erase_cached(struct rb_node *node, - struct rb_root_cached *root) -{ - if (root->rb_leftmost == node) - root->rb_leftmost = rb_next(node); - rb_erase(node, &root->rb_root); -} - -static inline void rb_replace_node_cached(struct rb_node *victim, - struct rb_node *_new, - struct rb_root_cached *root) -{ - if (root->rb_leftmost == victim) - root->rb_leftmost = _new; - rb_replace_node(victim, _new, &root->rb_root); -} - -static inline void rb_erase_init(struct rb_node *n, struct rb_root *root) -{ - rb_erase(n, root); - RB_CLEAR_NODE(n); -} - -/* ------------------------------------------------------------------ */ -/* Generic insert / find helpers (inline, using function pointers) */ -/* ------------------------------------------------------------------ */ - -static inline void -rb_add(struct rb_node *node, struct rb_root *tree, - bool (*less)(struct rb_node *, const struct rb_node *)) -{ - struct rb_node **link = &tree->rb_node; - struct rb_node *parent = nullptr; - - while (*link) { - parent = *link; - if (less(node, parent)) - link = &parent->rb_left; - else - link = &parent->rb_right; - } - - rb_link_node(node, parent, link); - rb_insert_color(node, tree); -} - -static inline void -rb_add_cached(struct rb_node *node, struct rb_root_cached *tree, - bool (*less)(struct rb_node *, const struct rb_node *)) -{ - struct rb_node **link = &tree->rb_root.rb_node; - struct rb_node *parent = nullptr; - bool leftmost = true; - - while (*link) { - parent = *link; - if (less(node, parent)) { - link = &parent->rb_left; - } else { - link = &parent->rb_right; - leftmost = false; - } - } - - rb_link_node(node, parent, link); - rb_insert_color_cached(node, tree, leftmost); -} - -static inline struct rb_node * -rb_find(const void *key, const struct rb_root *tree, - int (*cmp)(const void *key, const struct rb_node *)) -{ - struct rb_node *node = tree->rb_node; - - while (node) { - int c = cmp(key, node); - if (c < 0) - node = node->rb_left; - else if (c > 0) - node = node->rb_right; - else - return node; - } - return nullptr; -} - -static inline struct rb_node * -rb_find_add(struct rb_node *node, struct rb_root *tree, - int (*cmp)(struct rb_node *, const struct rb_node *)) -{ - struct rb_node **link = &tree->rb_node; - struct rb_node *parent = nullptr; - int c; - - while (*link) { - parent = *link; - c = cmp(node, parent); - if (c < 0) - link = &parent->rb_left; - else if (c > 0) - link = &parent->rb_right; - else - return parent; - } - - rb_link_node(node, parent, link); - rb_insert_color(node, tree); - return nullptr; -} - -/* ------------------------------------------------------------------ */ -/* Iteration macros */ -/* ------------------------------------------------------------------ */ - -#define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \ - for (pos = rb_entry_safe(rb_first_postorder(root), __typeof__(*pos), field); \ - pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \ - __typeof__(*pos), field); 1; }); \ - pos = n) - diff --git a/include/lume/rbtree_augmented.h b/include/lume/rbtree_augmented.h deleted file mode 100644 index d4559c4..0000000 --- a/include/lume/rbtree_augmented.h +++ /dev/null @@ -1,252 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Red-Black Trees — augmented operations & internal helpers - * Adapted from Linux kernel include/linux/rbtree_augmented.h - * - * (C) 1999 Andrea Arcangeli <andrea@suse.de> - * (C) 2002 David Woodhouse <dwmw2@infradead.org> - * (C) 2012 Michel Lespinasse <walken@google.com> - */ - -#pragma once - -#include <lume/rbtree.h> - -/* ------------------------------------------------------------------ */ -/* Augmented callback structure */ -/* ------------------------------------------------------------------ */ - -struct rb_augment_callbacks { - void (*propagate)(struct rb_node *node, struct rb_node *stop); - void (*copy)(struct rb_node *old, struct rb_node *_new); - void (*rotate)(struct rb_node *old, struct rb_node *_new); -}; - -extern "C" void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, - void (*augment_rotate)(struct rb_node *old, struct rb_node *_new)); - -extern "C" void __rb_erase_color(struct rb_node *parent, struct rb_root *root, - void (*augment_rotate)(struct rb_node *old, struct rb_node *_new)); - -static inline void -rb_insert_augmented(struct rb_node *node, struct rb_root *root, - const struct rb_augment_callbacks *augment) -{ - __rb_insert_augmented(node, root, augment->rotate); -} - -static inline void -rb_insert_augmented_cached(struct rb_node *node, - struct rb_root_cached *root, bool newleft, - const struct rb_augment_callbacks *augment) -{ - if (newleft) - root->rb_leftmost = node; - rb_insert_augmented(node, &root->rb_root, augment); -} - -/* ------------------------------------------------------------------ */ -/* Color / parent encoding helpers */ -/* ------------------------------------------------------------------ */ - -#define RB_RED 0 -#define RB_BLACK 1 - -#define __rb_parent(pc) ((struct rb_node *)(pc & ~3UL)) - -#define __rb_color(pc) ((pc) & 1) -#define __rb_is_black(pc) __rb_color(pc) -#define __rb_is_red(pc) (!__rb_color(pc)) -#define rb_color(rb) __rb_color((rb)->__rb_parent_color) -#define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color) -#define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color) - -static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) -{ - rb->__rb_parent_color = rb_color(rb) + (unsigned long)p; -} - -static inline void rb_set_parent_color(struct rb_node *rb, - struct rb_node *p, int color) -{ - rb->__rb_parent_color = (unsigned long)p + color; -} - -static inline void -__rb_change_child(struct rb_node *old, struct rb_node *_new, - struct rb_node *parent, struct rb_root *root) -{ - if (parent) { - if (parent->rb_left == old) - WRITE_ONCE(parent->rb_left, _new); - else - WRITE_ONCE(parent->rb_right, _new); - } else - WRITE_ONCE(root->rb_node, _new); -} - -/* ------------------------------------------------------------------ */ -/* Augmented erase (inline) */ -/* ------------------------------------------------------------------ */ - -static __always_inline struct rb_node * -__rb_erase_augmented(struct rb_node *node, struct rb_root *root, - const struct rb_augment_callbacks *augment) -{ - struct rb_node *child = node->rb_right; - struct rb_node *tmp = node->rb_left; - struct rb_node *parent, *rebalance; - unsigned long pc; - - if (!tmp) { - /* - * Case 1: node to erase has no more than 1 child (easy!) - */ - pc = node->__rb_parent_color; - parent = __rb_parent(pc); - __rb_change_child(node, child, parent, root); - if (child) { - child->__rb_parent_color = pc; - rebalance = nullptr; - } else - rebalance = __rb_is_black(pc) ? parent : nullptr; - tmp = parent; - } else if (!child) { - /* Still case 1, but this time the child is node->rb_left */ - tmp->__rb_parent_color = pc = node->__rb_parent_color; - parent = __rb_parent(pc); - __rb_change_child(node, tmp, parent, root); - rebalance = nullptr; - tmp = parent; - } else { - struct rb_node *successor = child, *child2; - - tmp = child->rb_left; - if (!tmp) { - /* - * Case 2: node's successor is its right child - */ - parent = successor; - child2 = successor->rb_right; - - augment->copy(node, successor); - } else { - /* - * Case 3: node's successor is leftmost under - * node's right child subtree - */ - do { - parent = successor; - successor = tmp; - tmp = tmp->rb_left; - } while (tmp); - child2 = successor->rb_right; - WRITE_ONCE(parent->rb_left, child2); - WRITE_ONCE(successor->rb_right, child); - rb_set_parent(child, successor); - - augment->copy(node, successor); - augment->propagate(parent, successor); - } - - tmp = node->rb_left; - WRITE_ONCE(successor->rb_left, tmp); - rb_set_parent(tmp, successor); - - pc = node->__rb_parent_color; - tmp = __rb_parent(pc); - __rb_change_child(node, successor, tmp, root); - - if (child2) { - rb_set_parent_color(child2, parent, RB_BLACK); - rebalance = nullptr; - } else { - rebalance = rb_is_black(successor) ? parent : nullptr; - } - successor->__rb_parent_color = pc; - tmp = successor; - } - - augment->propagate(tmp, nullptr); - return rebalance; -} - -static __always_inline void -rb_erase_augmented(struct rb_node *node, struct rb_root *root, - const struct rb_augment_callbacks *augment) -{ - struct rb_node *rebalance = __rb_erase_augmented(node, root, augment); - if (rebalance) - __rb_erase_color(rebalance, root, augment->rotate); -} - -static __always_inline void -rb_erase_augmented_cached(struct rb_node *node, struct rb_root_cached *root, - const struct rb_augment_callbacks *augment) -{ - if (root->rb_leftmost == node) - root->rb_leftmost = rb_next(node); - rb_erase_augmented(node, &root->rb_root, augment); -} - -/* ------------------------------------------------------------------ */ -/* Augmented callback declaration macros */ -/* ------------------------------------------------------------------ */ - -#define RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME, \ - RBSTRUCT, RBFIELD, RBAUGMENTED, RBCOMPUTE) \ -static inline void \ -RBNAME ## _propagate(struct rb_node *rb, struct rb_node *stop) \ -{ \ - while (rb != stop) { \ - RBSTRUCT *node = rb_entry(rb, RBSTRUCT, RBFIELD); \ - if (RBCOMPUTE(node, true)) \ - break; \ - rb = rb_parent(&node->RBFIELD); \ - } \ -} \ -static inline void \ -RBNAME ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \ -{ \ - RBSTRUCT *old_ = rb_entry(rb_old, RBSTRUCT, RBFIELD); \ - RBSTRUCT *new_ = rb_entry(rb_new, RBSTRUCT, RBFIELD); \ - new_->RBAUGMENTED = old_->RBAUGMENTED; \ -} \ -static void \ -RBNAME ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ -{ \ - RBSTRUCT *old_ = rb_entry(rb_old, RBSTRUCT, RBFIELD); \ - RBSTRUCT *new_ = rb_entry(rb_new, RBSTRUCT, RBFIELD); \ - new_->RBAUGMENTED = old_->RBAUGMENTED; \ - RBCOMPUTE(old_, false); \ -} \ -RBSTATIC const struct rb_augment_callbacks RBNAME = { \ - RBNAME ## _propagate, \ - RBNAME ## _copy, \ - RBNAME ## _rotate \ -}; - -#define RB_DECLARE_CALLBACKS_MAX(RBSTATIC, RBNAME, RBSTRUCT, RBFIELD, \ - RBTYPE, RBAUGMENTED, RBCOMPUTE) \ -static inline bool RBNAME ## _compute_max(RBSTRUCT *node, bool exit_early) \ -{ \ - RBSTRUCT *child; \ - RBTYPE max = RBCOMPUTE(node); \ - if (node->RBFIELD.rb_left) { \ - child = rb_entry(node->RBFIELD.rb_left, RBSTRUCT, RBFIELD); \ - if (child->RBAUGMENTED > max) \ - max = child->RBAUGMENTED; \ - } \ - if (node->RBFIELD.rb_right) { \ - child = rb_entry(node->RBFIELD.rb_right, RBSTRUCT, RBFIELD); \ - if (child->RBAUGMENTED > max) \ - max = child->RBAUGMENTED; \ - } \ - if (exit_early && node->RBAUGMENTED == max) \ - return true; \ - node->RBAUGMENTED = max; \ - return false; \ -} \ -RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME, \ - RBSTRUCT, RBFIELD, RBAUGMENTED, RBNAME ## _compute_max) - diff --git a/include/lume/rbtree_types.h b/include/lume/rbtree_types.h deleted file mode 100644 index 688ade4..0000000 --- a/include/lume/rbtree_types.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Red-Black Tree type definitions - * Adapted from Linux kernel include/linux/rbtree_types.h - */ - -#pragma once - -#include <lume/types.h> - -struct rb_node { - unsigned long __rb_parent_color; - struct rb_node *rb_right; - struct rb_node *rb_left; -} __attribute__((aligned(sizeof(long)))); - -struct rb_root { - struct rb_node *rb_node; -}; - -struct rb_root_cached { - struct rb_root rb_root; - struct rb_node *rb_leftmost; -}; - -#define RB_ROOT (struct rb_root) { nullptr, } -#define RB_ROOT_CACHED (struct rb_root_cached) { {nullptr, }, nullptr } - diff --git a/include/lume/sched.h b/include/lume/sched.h deleted file mode 100644 index ab26bac..0000000 --- a/include/lume/sched.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Scheduler Public Interface - * - * Linux-style sched_class core with per-CPU runqueues. - * Phase 2: O(1) bitmap class is the default scheduling class. - * - * Reference: docs/specs/scheduler.md - */ - -#include <lume/types.h> -#include <lume/config.h> - -struct TaskControlBlock; - -/* ======================================================================== - * Scheduler Constants — driven by CONFIG_xxx (see scripts/Kconfig.mk) - * ======================================================================== */ - -inline constexpr int kNumPriorities = CONFIG_NR_PRIORITIES; -inline constexpr int kDefaultPriority = CONFIG_DEFAULT_PRIORITY; -inline constexpr int kDefaultTimeSlice = CONFIG_DEFAULT_TIMESLICE; -inline constexpr int kIdlePriority = CONFIG_IDLE_PRIORITY; - -/* ======================================================================== - * Initialization - * ======================================================================== */ - -/* BSP: initialize all RunQueues, create BSP idle thread and boot TCB. */ -void sched_init(); - -/* AP: create per-CPU idle thread and boot TCB. */ -void sched_init_ap(); - -/* ======================================================================== - * Core Scheduling - * ======================================================================== */ - -/* Main scheduling entry point. Picks the next task and context-switches. - * Called voluntarily (yield, sleep, exit) or from trap return path. */ -void schedule(); - -/* Timer tick handler. Delegates to current task's sched_class. - * Called from MI trap layer in interrupt context. */ -void sched_tick(); - -/* Check if rescheduling is needed (called before returning to user mode). */ -void sched_check_preempt(); - -/* Voluntarily yield the current time slice. */ -void sched_yield(); - -/* ======================================================================== - * Task Queue Management (used by task.cc, waitqueue.cc) - * ======================================================================== */ - -/* Make a task runnable: add it to its CPU's RunQueue. */ -void sched_enqueue(TaskControlBlock* task); - -/* Mark a task as sleeping: remove it from the RunQueue. */ -void sched_dequeue(TaskControlBlock* task); - -/* ======================================================================== - * Time Slice Policy - * ======================================================================== */ - -/* Convert priority level to time slice length. - * Higher priority (lower number) → longer time slice. */ -int32 priority_to_timeslice(uint8 priority); - -/* ======================================================================== - * Task Migration & Load Balancing - * ======================================================================== */ - -/* - * sched_migrate_task — Move a task from its current CPU to target_cpu. - * - * The task must NOT be the currently running task. It is dequeued from - * its old runqueue and enqueued onto the target. Both runqueue locks - * are acquired in cpu_id order to prevent deadlock. - * - * Returns 0 on success, -EINVAL if task is current or target is invalid. - */ -int sched_migrate_task(TaskControlBlock* task, uint8 target_cpu); - -/* - * sched_balance — Periodic load balancer. - * - * Called from sched_tick(). Checks if any CPU has significantly more - * runnable tasks and pulls work to the local runqueue. This is a - * simplified version of Linux's load_balance(). - */ -void sched_balance(); - -/* - * sched_nr_running — Get the number of runnable tasks on a CPU. - */ -uint32 sched_nr_running(uint32 cpu_id); diff --git a/include/lume/sched_class.h b/include/lume/sched_class.h deleted file mode 100644 index 08686c1..0000000 --- a/include/lume/sched_class.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Scheduler Class Interface (Linux-style) - * - * Each scheduling algorithm implements a sched_class and is chained - * in priority order. The scheduler core walks the chain to select - * the next runnable task. - */ - -#include <lume/types.h> - -struct RunQueue; -struct TaskControlBlock; - -struct SchedClass { - const char* name; - const SchedClass* next; // Linked list order: higher priority first - - void (*init_rq)(RunQueue* rq); - - void (*enqueue_task)(RunQueue* rq, TaskControlBlock* task); - void (*dequeue_task)(RunQueue* rq, TaskControlBlock* task); - TaskControlBlock* (*pick_next_task)(RunQueue* rq); - void (*put_prev_task)(RunQueue* rq, TaskControlBlock* task); - - void (*task_tick)(RunQueue* rq, TaskControlBlock* curr); - void (*yield_task)(RunQueue* rq, TaskControlBlock* curr); -}; - -extern const SchedClass g_sched_class_o1; -extern const SchedClass g_sched_class_idle; diff --git a/include/lume/selftest.h b/include/lume/selftest.h deleted file mode 100644 index 7040986..0000000 --- a/include/lume/selftest.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Boot Self-Test Framework - * - * Minimal assertion-based test harness that runs during kernel_main() - * after all subsystems are initialized. Each test is a void function - * that calls ST_ASSERT / ST_ASSERT_EQ macros. On failure, prints - * the failing expression and panics. - * - * Usage: - * void selftest_pmm(); // defined in test/test_pmm.cc - * void selftest_slab(); // defined in test/test_slab.cc - * - * All self-tests run only on BSP in single-core mode. - */ - -#include <lume/types.h> -#include <lume/klog.h> -#include <lume/kprintf.h> - -#define ST_ASSERT(cond) \ - do { \ - if (!(cond)) { \ - kprintf("[FAIL] %s:%d: assertion failed: %s\n", \ - __FILE__, __LINE__, #cond); \ - kernel_panic("selftest failed", #cond); \ - } \ - } while (0) - -#define ST_ASSERT_EQ(a, b) \ - do { \ - auto _a = (a); auto _b = (b); \ - if (_a != _b) { \ - kprintf("[FAIL] %s:%d: %s != %s (0x%llx != 0x%llx)\n", \ - __FILE__, __LINE__, #a, #b, \ - (uint64)(uintptr)(_a), (uint64)(uintptr)(_b)); \ - kernel_panic("selftest failed", #a " != " #b); \ - } \ - } while (0) - -#define ST_ASSERT_NE(a, b) \ - do { \ - auto _a = (a); auto _b = (b); \ - if (_a == _b) { \ - kprintf("[FAIL] %s:%d: %s == %s (both 0x%llx)\n", \ - __FILE__, __LINE__, #a, #b, \ - (uint64)(uintptr)(_a)); \ - kernel_panic("selftest failed", #a " == " #b); \ - } \ - } while (0) - -/* Announce a test suite beginning/end */ -inline void st_begin(const char* name) -{ - kprintf("[test] %s ... ", name); -} - -inline void st_pass() -{ - kprintf("PASS\n"); -} diff --git a/include/lume/setup.h b/include/lume/setup.h deleted file mode 100644 index f8e6cb6..0000000 --- a/include/lume/setup.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#ifndef _LUME_SETUP_H -#define _LUME_SETUP_H - -/* - * Boot-time interfaces called between assembly and C. - * - * Mirrors the subset of Linux include/linux/setup.h relevant to LumeOS's - * Linux-aligned RISC-V boot flow: - * - * setup_vm Build early_pg_dir / trampoline_pg_dir before - * the MMU is enabled. Filled kernel_map for - * all subsequent code to consult. - * relocate_enable_mmu Switch SATP, jump to higher-half, apply - * .rela.dyn via relocate_kernel. - * relocate_kernel Walk .rela.dyn, patch R_RISCV_RELATIVE - * slots with addend + kaslr_offset. - * - * kernel_main (LumeOS's equivalent of Linux's start_kernel) is declared - * in kernel/main.cc and re-declared in arch-side glue — kept local to - * that file to avoid creating an artificial public API for the lone - * call site in head.S. - */ - -#include <lume/types.h> -#include <asm/pgtable.h> - -#ifdef __cplusplus -extern "C" { -#endif - -void setup_vm(uintptr_t load_pa, uintptr_t dtb_pa); -void relocate_enable_mmu(pgd_t *pgdir); -void relocate_kernel(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _LUME_SETUP_H */ diff --git a/include/lume/signal.h b/include/lume/signal.h deleted file mode 100644 index 05b7542..0000000 --- a/include/lume/signal.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Signal Infrastructure — Core signal delivery API - * - * Provides the interface between trap handling, signal delivery, - * and user-space signal handler execution. - * - * Reference: Linux include/linux/sched/signal.h - */ - -#include <lume/types.h> - -struct TaskControlBlock; -struct sighand_struct; -namespace arch { struct TrapFrame; } - -/* ------------------------------------------------------------------ - * sighand_struct lifecycle (Linux kernel/fork.c:copy_sighand pattern) - * ------------------------------------------------------------------ */ - -sighand_struct* alloc_sighand(); -sighand_struct* copy_sighand(sighand_struct* parent); -void get_sighand(sighand_struct* sh); -void put_sighand(sighand_struct* sh); - -/* - * force_sig_fault — Deliver a fault-induced signal to the current task. - * - * Called from trap handler when a user-mode exception cannot be resolved. - * Bypasses the blocked mask and enqueues the signal. - * - * @signo: Signal number (SIGSEGV, SIGBUS, SIGILL, SIGFPE, etc.) - * @code: si_code for siginfo_t (e.g., SEGV_MAPERR, SEGV_ACCERR) - * @addr: Fault address (stval / badaddr) - */ -void force_sig_fault(int signo, int code, uint64 addr); - -/* - * do_signal — Process pending signals before returning to user mode. - * - * Called at the end of trap_handle() when origin == FromUser. - * If a signal is pending and a handler is registered, constructs - * a signal frame on the user stack and redirects epc. - * - * @tf: TrapFrame to modify if signal delivery is needed. - */ -void do_signal(arch::TrapFrame* tf); - -/* - * signal_pending — Check if the task has unblocked pending signals. - * - * Used by blocking syscalls (e.g., n_tty_read) to detect whether - * they should return -EINTR. - */ -bool signal_pending(TaskControlBlock* task); - diff --git a/include/lume/signal_nr.h b/include/lume/signal_nr.h deleted file mode 100644 index 8e595d7..0000000 --- a/include/lume/signal_nr.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Linux-compatible signal numbers and related ABI constants. - * - * This mirrors the common Linux UAPI numbering used by asm-generic/signal.h. - * Keep the values stable so user-space binaries see the same numbers. - */ - -inline constexpr int _NSIG = 64; -inline constexpr int _NSIG_BPW = sizeof(unsigned long) * 8; -inline constexpr int _NSIG_WORDS = _NSIG / _NSIG_BPW; - -inline constexpr int SIGHUP = 1; -inline constexpr int SIGINT = 2; -inline constexpr int SIGQUIT = 3; -inline constexpr int SIGILL = 4; -inline constexpr int SIGTRAP = 5; -inline constexpr int SIGABRT = 6; -inline constexpr int SIGIOT = SIGABRT; -inline constexpr int SIGBUS = 7; -inline constexpr int SIGFPE = 8; -inline constexpr int SIGKILL = 9; -inline constexpr int SIGUSR1 = 10; -inline constexpr int SIGSEGV = 11; -inline constexpr int SIGUSR2 = 12; -inline constexpr int SIGPIPE = 13; -inline constexpr int SIGALRM = 14; -inline constexpr int SIGTERM = 15; -inline constexpr int SIGSTKFLT = 16; -inline constexpr int SIGCHLD = 17; -inline constexpr int SIGCONT = 18; -inline constexpr int SIGSTOP = 19; -inline constexpr int SIGTSTP = 20; -inline constexpr int SIGTTIN = 21; -inline constexpr int SIGTTOU = 22; -inline constexpr int SIGURG = 23; -inline constexpr int SIGXCPU = 24; -inline constexpr int SIGXFSZ = 25; -inline constexpr int SIGVTALRM = 26; -inline constexpr int SIGPROF = 27; -inline constexpr int SIGWINCH = 28; -inline constexpr int SIGIO = 29; -inline constexpr int SIGPOLL = SIGIO; -inline constexpr int SIGPWR = 30; -inline constexpr int SIGSYS = 31; -inline constexpr int SIGUNUSED = 31; - -/* Real-time signals start here in Linux UAPI. */ -inline constexpr int SIGRTMIN = 32; -inline constexpr int SIGRTMAX = _NSIG; diff --git a/include/lume/signal_types.h b/include/lume/signal_types.h deleted file mode 100644 index f66231b..0000000 --- a/include/lume/signal_types.h +++ /dev/null @@ -1,263 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Signal Types — Linux-compatible structures for signal delivery - * - * Follows the RISC-V LP64 ABI layout so that user-space programs - * compiled with musl / glibc see the correct struct sizes. - * - * Reference: Linux include/uapi/asm-generic/signal.h - * Linux include/uapi/asm-generic/siginfo.h - */ - -#include <lume/types.h> -#include <lume/signal_nr.h> -#include <lume/list.h> -#include <kernel/sync/spinlock.h> - -/* ================================================================== */ -/* Signal set (64-bit bitmap) */ -/* ================================================================== */ - -struct sigset_t { - uint64 sig[_NSIG_WORDS]; /* _NSIG_WORDS = 1 on LP64 */ - - void clear() { for (auto& s : sig) s = 0; } - void fill() { for (auto& s : sig) s = ~0ULL; } - void add(int signo) { sig[(signo-1)/64] |= (1ULL << ((signo-1)%64)); } - void del(int signo) { sig[(signo-1)/64] &= ~(1ULL << ((signo-1)%64)); } - bool has(int signo) const { return (sig[(signo-1)/64] >> ((signo-1)%64)) & 1; } - bool is_empty() const { for (auto s : sig) if (s) return false; return true; } - - sigset_t operator&(const sigset_t& o) const { - sigset_t r; - for (int i = 0; i < _NSIG_WORDS; i++) r.sig[i] = sig[i] & o.sig[i]; - return r; - } - sigset_t operator|(const sigset_t& o) const { - sigset_t r; - for (int i = 0; i < _NSIG_WORDS; i++) r.sig[i] = sig[i] | o.sig[i]; - return r; - } - sigset_t operator~() const { - sigset_t r; - for (int i = 0; i < _NSIG_WORDS; i++) r.sig[i] = ~sig[i]; - return r; - } -}; - -/* ================================================================== */ -/* siginfo_t (simplified, Linux UAPI compatible layout) */ -/* ================================================================== */ - -struct kernel_siginfo { - int si_signo; - int si_errno; - int si_code; - int _pad0; /* alignment */ - - union { - /* kill() */ - struct { - int32 _pid; - int32 _uid; - } _kill; - - /* SIGCHLD */ - struct { - int32 _pid; - int32 _uid; - int _status; - long _utime; - long _stime; - } _sigchld; - - /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP */ - struct { - uint64 _addr; - } _sigfault; - - /* Pad to 128 bytes total (Linux SI_MAX_SIZE) */ - char _pad[128 - 4*sizeof(int)]; - } _sifields; -}; - -/* ================================================================== */ -/* Signal action (kernel representation) */ -/* ================================================================== */ - -/* sa_flags bits (Linux UAPI) */ -inline constexpr uint64 SA_NOCLDSTOP = 0x00000001; -inline constexpr uint64 SA_NOCLDWAIT = 0x00000002; -inline constexpr uint64 SA_SIGINFO = 0x00000004; -inline constexpr uint64 SA_RESTORER = 0x04000000; -inline constexpr uint64 SA_ONSTACK = 0x08000000; -inline constexpr uint64 SA_RESTART = 0x10000000; -inline constexpr uint64 SA_NODEFER = 0x40000000; -inline constexpr uint64 SA_RESETHAND = 0x80000000; - -/* Special handler values */ -inline constexpr uint64 SIG_DFL = 0; -inline constexpr uint64 SIG_IGN = 1; -inline constexpr uint64 SIG_ERR = static_cast<uint64>(-1); - -struct kernel_sigaction { - uint64 sa_handler; /* handler address or SIG_DFL/SIG_IGN */ - uint64 sa_flags; - uint64 sa_restorer; /* sigreturn trampoline (SA_RESTORER) */ - sigset_t sa_mask; /* signals blocked during handler */ -}; - -/* ================================================================== */ -/* Per-task signal state */ -/* ================================================================== */ - -/* Queued signal entry */ -struct sigqueue { - list_node list; - kernel_siginfo info; -}; - -/* Pending signal set + queue */ -struct sigpending { - list_node list; /* list of sigqueue entries */ - sigset_t signal; /* bitmap of pending signals */ - - void init() { - list.init(); - signal.clear(); - } -}; - -/* Signal handler table (shared between threads via CLONE_SIGHAND). - * - * Linux pattern (kernel/fork.c:copy_sighand): one sighand_struct per - * thread group by default, shared across CLONE_SIGHAND siblings, - * refcounted, freed when the last referencing task exits. Its - * `siglock` guards BOTH the action table and every per-task `pending` - * list of every task that references this sighand. That single-lock - * model is what lets send/dequeue/discard race-free without per-list - * locks. */ -struct sighand_struct { - Spinlock siglock; - uint32 refcount; /* # tasks sharing this sighand (≥1) */ - kernel_sigaction action[_NSIG]; - - void init() { - siglock.init("sighand"); - refcount = 1; - for (auto& a : action) { - a.sa_handler = SIG_DFL; - a.sa_flags = 0; - a.sa_restorer = 0; - a.sa_mask.clear(); - } - } -}; - -/* ================================================================== */ -/* signal_struct — per-thread-group shared state */ -/* ================================================================== */ - -struct TaskControlBlock; -struct tty_struct; - -/* - * Linux's signal_struct is the per-thread-group container holding: - * - Process group / session identity (pgid, sid) - * - Controlling terminal (tty) - * - Misc state shared across CLONE_THREAD siblings - * - * Refcount tracks the number of tasks in the thread group; when the last - * task in the group exits, the signal_struct is freed. Detachment from - * the pgrp hash also happens at that point. - * - * `pgrp_link` makes this signal_struct a member of one pgrp bucket; the - * pgrp subsystem walks the bucket to enumerate all thread groups whose - * pgid hashes there. - */ -struct signal_struct { - Spinlock lock; - uint32 refcount; /* # tasks sharing this (≥1) */ - int32 pgid; /* process group id */ - int32 sid; /* session id */ - tty_struct* tty; /* controlling tty (or nullptr) */ - int32 tty_old_pgrp; /* SIGHUP target on TIOCNOTTY */ - TaskControlBlock* leader; /* thread-group leader (pid==tgid) */ - list_node pgrp_link; /* on pgrp hash bucket */ - - void init(int32 leader_pid, TaskControlBlock* tg_leader) { - lock.init("signal"); - refcount = 1; - pgid = leader_pid; - sid = leader_pid; - tty = nullptr; - tty_old_pgrp = 0; - leader = tg_leader; - pgrp_link.init(); - } -}; - -/* ================================================================== */ -/* Default signal dispositions */ -/* ================================================================== */ - -enum SigDefaultAction { - SIG_ACT_TERM, /* Terminate */ - SIG_ACT_IGN, /* Ignore */ - SIG_ACT_CORE, /* Terminate + core dump */ - SIG_ACT_STOP, /* Stop process */ - SIG_ACT_CONT, /* Continue if stopped */ -}; - -/* Returns the default action for a standard signal */ -inline SigDefaultAction sig_default_action(int sig) -{ - switch (sig) { - case SIGCHLD: - case SIGURG: - case SIGWINCH: - return SIG_ACT_IGN; - - case SIGCONT: - return SIG_ACT_CONT; - - case SIGSTOP: - case SIGTSTP: - case SIGTTIN: - case SIGTTOU: - return SIG_ACT_STOP; - - case SIGQUIT: - case SIGILL: - case SIGTRAP: - case SIGABRT: - case SIGBUS: - case SIGFPE: - case SIGSEGV: - case SIGXCPU: - case SIGXFSZ: - case SIGSYS: - return SIG_ACT_CORE; - - default: - return SIG_ACT_TERM; - } -} - -/* SIG_KERNEL_ONLY: cannot be caught or ignored */ -inline bool sig_kernel_only(int sig) -{ - return sig == SIGKILL || sig == SIGSTOP; -} - -/* ================================================================== */ -/* SigprocMask how values (Linux UAPI) */ -/* ================================================================== */ - -inline constexpr int SIG_BLOCK = 0; -inline constexpr int SIG_UNBLOCK = 1; -inline constexpr int SIG_SETMASK = 2; diff --git a/include/lume/slab.h b/include/lume/slab.h deleted file mode 100644 index 4ebade1..0000000 --- a/include/lume/slab.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * SLUB public API - * - * This header exposes the allocator entry points to the rest of the kernel. - * Implementation details stay in mm/slab.h and mm/slab.cc. - */ - -#include <lume/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initialize global slab caches. */ -void slab_init(); - -/* Allocate/free kernel memory. */ -void* kmalloc(uint32 size); -void kfree(void* ptr); - -#ifdef __cplusplus -} -#endif diff --git a/include/lume/smp.h b/include/lume/smp.h deleted file mode 100644 index a5292b6..0000000 --- a/include/lume/smp.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * smp.h — Machine-Independent SMP primitives - * - * Provides cross-CPU communication (IPI) and TLB coordination. - * The MI interface calls through to arch-specific backends - * (e.g. SBI on RISC-V, APIC on x86). - * - * Reference: docs/specs/linux_abi_mm_plan.md §SMP - */ - -#include <lume/types.h> -#include <lume/atomic.h> -#include <lume/config.h> - -/* - * IPI reasons — each bit in the per-CPU pending mask - * corresponds to one reason. Multiple reasons can be - * pending simultaneously. - */ -enum IpiReason : uint32 { - IPI_RESCHEDULE = (1U << 0), /* Target should call schedule() */ - IPI_TLB_SHOOTDOWN = (1U << 1), /* Target should flush TLB */ - IPI_CALL_FUNCTION = (1U << 2), /* Target should run a function */ - IPI_HALT = (1U << 3), /* Target should halt */ -}; - -/* - * Per-CPU IPI pending state. - * Written by sender (atomically), consumed by receiver in IRQ context. - */ -struct IpiData { - lume::atomic<uint32> pending; /* Bitmask of IpiReason */ - - /* TLB shootdown payload */ - uint64 tlb_start; - uint64 tlb_end; -}; - -/* Per-CPU IPI data array (BSS zero-initialized) */ -extern IpiData g_ipi_data[kMaxCpus]; - -/* - * smp_send_ipi — Send an IPI to a set of CPUs - * - * @cpu_mask: bitmask of target CPU IDs (bit N = CPU N) - * @reason: reason bits to set in the target's pending mask - * - * Safe to call from any context (interrupt or process). - */ -void smp_send_ipi(uint64 cpu_mask, uint32 reason); - -/* - * smp_send_reschedule — Convenience: send reschedule IPI to one CPU - */ -inline void smp_send_reschedule(uint8 cpu_id) -{ - smp_send_ipi(1ULL << cpu_id, IPI_RESCHEDULE); -} - -/* - * smp_init — Initialize SMP subsystem (called from BSP after trap_init) - */ -void smp_init(); - -/* - * smp_handle_ipi — Called from trap handler on receiving S-mode - * software interrupt. Processes all pending IPI reasons. - */ -void smp_handle_ipi(); diff --git a/include/lume/stdarg.h b/include/lume/stdarg.h deleted file mode 100644 index c8dc7f4..0000000 --- a/include/lume/stdarg.h +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -#ifndef _LINUX_STDARG_H -#define _LINUX_STDARG_H - -typedef __builtin_va_list va_list; -#define va_start(v, l) __builtin_va_start(v, l) -#define va_end(v) __builtin_va_end(v) -#define va_arg(v, T) __builtin_va_arg(v, T) -#define va_copy(d, s) __builtin_va_copy(d, s) - -#endif diff --git a/include/lume/stringify.h b/include/lume/stringify.h deleted file mode 100644 index 0e84cbe..0000000 --- a/include/lume/stringify.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __LINUX_STRINGIFY_H -#define __LINUX_STRINGIFY_H - -/* Indirect stringification. Doing two levels allows the parameter to be a - * macro itself. For example, compile with -DFOO=bar, __stringify(FOO) - * converts to "bar". - */ - -#define __stringify_1(x...) #x -#define __stringify(x...) __stringify_1(x) - -#define FILE_LINE __FILE__ ":" __stringify(__LINE__) - -#endif /* !__LINUX_STRINGIFY_H */ diff --git a/include/lume/syscall.h b/include/lume/syscall.h deleted file mode 100644 index 8185096..0000000 --- a/include/lume/syscall.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * System Call Interface — Machine-Independent Layer - * - * Defines the unified syscall handler signature and the MI dispatch function. - * MD layer (arch/riscv/syscall/syscall_md.cc) extracts registers into args[6] - * and calls syscall_dispatch(). - * - * Reference: docs/specs/syscall.md §4 - */ - -#include <lume/types.h> - -/* Unified syscall handler signature. - * All arguments and return value are register-width (uint64). - * Individual sys_* functions cast internally. */ -using SyscallHandler = int64 (*)(uint64, uint64, uint64, - uint64, uint64, uint64); - -/* MI-layer syscall dispatcher. - * Called by MD layer after extracting syscall number and arguments. - * Returns the syscall result (negative errno on error). */ -int64 syscall_dispatch(uint64 nr, uint64 args[6]); - -/* Register all implemented syscall handlers into the jump table. - * Called from kernel_main() after sched_init(). */ -void syscall_init(); - -/* MD-layer entry point — called from trap handler on TrapCause::Syscall. - * Extracts registers from TrapFrame, calls syscall_dispatch, writes result. */ -namespace arch { -struct TrapFrame; -} -void syscall_dispatch_md(arch::TrapFrame* tf); diff --git a/include/lume/syscall_nr.h b/include/lume/syscall_nr.h deleted file mode 100644 index 29e3904..0000000 --- a/include/lume/syscall_nr.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * System Call Numbers — RISC-V LP64 (asm-generic/unistd.h compatible) - * - * Numbering strictly follows Linux asm-generic so that musl libc / Busybox - * binaries can be run without modification. - * - * Reference: docs/specs/syscall.md §4.3 - */ - -inline constexpr int SYS_exit = 93; -inline constexpr int SYS_exit_group = 94; -inline constexpr int SYS_set_tid_address = 96; -inline constexpr int SYS_sched_yield = 124; -inline constexpr int SYS_uname = 160; -inline constexpr int SYS_getpid = 172; -inline constexpr int SYS_getppid = 173; -inline constexpr int SYS_getuid = 174; -inline constexpr int SYS_getgid = 176; -inline constexpr int SYS_gettid = 178; -inline constexpr int SYS_brk = 214; -inline constexpr int SYS_munmap = 215; -inline constexpr int SYS_clone = 220; -inline constexpr int SYS_execve = 221; -inline constexpr int SYS_mmap = 222; -inline constexpr int SYS_mprotect = 226; -inline constexpr int SYS_wait4 = 260; - -inline constexpr int SYS_getcwd = 17; -inline constexpr int SYS_dup = 23; -inline constexpr int SYS_dup3 = 24; -inline constexpr int SYS_ioctl = 29; -inline constexpr int SYS_mkdirat = 34; -inline constexpr int SYS_unlinkat = 35; -inline constexpr int SYS_chdir = 49; -inline constexpr int SYS_openat = 56; -inline constexpr int SYS_close = 57; -inline constexpr int SYS_pipe2 = 59; -inline constexpr int SYS_lseek = 62; -inline constexpr int SYS_read = 63; -inline constexpr int SYS_write = 64; -inline constexpr int SYS_writev = 66; -inline constexpr int SYS_ppoll = 73; -inline constexpr int SYS_fstatat = 79; -inline constexpr int SYS_fstat = 80; -inline constexpr int SYS_getdents64 = 61; - -inline constexpr int SYS_fcntl = 25; -inline constexpr int SYS_linkat = 37; -inline constexpr int SYS_mount = 40; -inline constexpr int SYS_umount2 = 39; - -inline constexpr int SYS_kill = 129; -inline constexpr int SYS_tkill = 130; -inline constexpr int SYS_tgkill = 131; -inline constexpr int SYS_sigaltstack = 132; -inline constexpr int SYS_rt_sigaction = 134; -inline constexpr int SYS_rt_sigprocmask = 135; -inline constexpr int SYS_rt_sigreturn = 139; -inline constexpr int SYS_reboot = 142; -inline constexpr int SYS_setpgid = 154; -inline constexpr int SYS_getpgid = 155; -inline constexpr int SYS_getsid = 156; -inline constexpr int SYS_setsid = 157; -inline constexpr int SYS_prctl = 167; -inline constexpr int SYS_geteuid = 175; -inline constexpr int SYS_getegid = 177; - -inline constexpr int SYS_futex = 98; -inline constexpr int SYS_nanosleep = 101; -inline constexpr int SYS_clock_gettime = 113; -inline constexpr int SYS_epoll_create1 = 20; -inline constexpr int SYS_epoll_ctl = 21; -inline constexpr int SYS_epoll_pwait = 22; - -inline constexpr int SYS_rt_sigtimedwait = 137; -inline constexpr int SYS_socket = 198; -inline constexpr int SYS_sendto = 206; diff --git a/include/lume/task.h b/include/lume/task.h deleted file mode 100644 index e959147..0000000 --- a/include/lume/task.h +++ /dev/null @@ -1,144 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Task Control Block & Task State - * - * Central representation of every execution context in LumeOS, - * whether kernel thread or (future) user process. - * - * Reference: docs/specs/task.md §3.1, docs/specs/scheduler.md §3.1 - */ - -#include <lume/types.h> -#include <lume/config.h> -#include <lume/list.h> -#include <arch/context.h> -#include <arch/trapframe.h> -#include <arch/fpstate.h> -#include <lume/waitqueue.h> -#include <lume/signal_types.h> - -/* Forward declarations */ -struct VmSpace; -struct SchedClass; - -/* ======================================================================== - * Task State Machine - * ======================================================================== */ - -enum class TaskState : uint8 { - Runnable = 0, // In a Per-CPU ready queue - Running = 1, // Currently executing on a CPU - Sleeping = 2, // Blocked on a WaitQueue - Zombie = 3, // Exited, waiting for parent wait() - Dead = 4, // Fully reclaimed, TCB can be freed - Stopped = 5, // Job control: SIGSTOP/SIGTSTP/SIGTTIN/SIGTTOU -}; - -/* ======================================================================== - * Task Flags - * ======================================================================== */ - -inline constexpr uint8 TF_KTHREAD = 0x01; // Kernel thread (never enters user mode) -inline constexpr uint8 TF_IDLE = 0x02; // Idle thread -inline constexpr uint8 TF_INIT = 0x04; // init process (PID 1) - -/* ======================================================================== - * Kernel Stack - * ======================================================================== */ - -inline constexpr uint64 kKernelStackSize = CONFIG_KERNEL_STACK_SIZE; -inline constexpr int kKernelStackOrder = (kKernelStackSize <= 4096) ? 0 - : (kKernelStackSize <= 8192) ? 1 - : (kKernelStackSize <= 16384) ? 2 - : (kKernelStackSize <= 32768) ? 3 : 4; -inline constexpr uint64 kStackCanary = 0xDEAD'BEEF'CAFE'BABEULL; - -/* ======================================================================== - * Task Control Block - * ======================================================================== */ - -struct TaskControlBlock { - /* ===== Scheduler hot fields (cache-line optimized) ===== */ - TaskState state; // Current state - uint8 priority; // Static priority [0, 31] - uint8 cpu_id; // Pinned CPU (Phase 2: no migration) - uint8 flags; // TF_KTHREAD | TF_IDLE | TF_INIT - - int32 time_slice; // Remaining time slice (ticks) - int32 pid; // Unique task ID (Linux: tid) - int32 tgid; // Thread group ID (Linux: pid) - int32 preempt_count; // >0: preemption disabled (holding locks etc.) - - list_node run_link; // RunQueue list node - list_node all_link; // Global task list node - - /* ===== Context ===== */ - arch::Context context; // Callee-saved registers (scheduler switch) - arch::TrapFrame* trapframe; // Trap frame (user-mode entry/exit) - arch::FpState fpstate; // FPU register state (f0-f31 + fcsr) - - /* ===== Kernel Stack ===== */ - uint64 kstack_pa; // Physical address - uint64 kstack_va; // Virtual address (stack bottom) - - /* ===== Address Space ===== */ - VmSpace* mm; // nullptr = kernel thread - - /* ===== Per-task lock ===== - * Protects: parent, children, sibling, exit_code, state transitions. - * Lock ordering: task->lock -> g_task_list_lock (never reverse). */ - Spinlock lock; - - /* ===== Task Hierarchy ===== */ - TaskControlBlock* parent; - list_node children; // Children list head - list_node sibling; // Sibling list node - WaitQueue wait_chld; // Parent waits on this for children to exit - - /* ===== Exit ===== */ - int32 exit_code; - int32 exit_signal; // Linux: signal sent to parent on exit. - // SIGCHLD = notify parent, become zombie - // -1 = auto-reap (kthreads) - uint64 clear_child_tid; // CLONE_CHILD_CLEARTID: write 0 here on exit - - /* ===== Job control reporting ===== - * stopped_code: 0 means "no pending stop notification"; non-zero is the - * Linux wstatus value to hand back from wait4(WUNTRACED). Cleared - * after the parent consumes it via wait4 (or task termination). - * notify_continued: set when SIGCONT resumes us; consumed by - * wait4(WCONTINUED). */ - int32 stopped_code; - bool notify_continued; - - /* ===== Scheduler class metadata ===== */ - const SchedClass* sched_class; - void* sched_entity; - - /* ===== VFS ===== */ - struct files_struct* files; // Per-task fd table (shared via CLONE_FILES) - struct fs_struct* fs; // cwd/root (shared via CLONE_FS) - - /* ===== Signals ===== */ - struct sigpending pending; // Per-task pending signal queue - sigset_t blocked; // Blocked signal mask - struct sighand_struct* sighand; // Signal handler table (shared via CLONE_SIGHAND) - struct signal_struct* signal; // Thread-group identity: pgid/sid/ctty (shared via CLONE_THREAD) - - /* ===== Debug ===== */ - const char* name; -}; - -/* ======================================================================== - * current_task() — fast access to the running task on this CPU - * - * Must be called with interrupts disabled or while holding a spinlock. - * ======================================================================== */ -TaskControlBlock* current_task(); - -/* Terminate the current task with a signal. */ -void task_kill_current(int sig); diff --git a/include/lume/timer.h b/include/lume/timer.h deleted file mode 100644 index 9bdddd5..0000000 --- a/include/lume/timer.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -#include <lume/types.h> - -/* - * MI Timer Subsystem - */ - -#include <lume/list.h> - -struct TimerList { - list_node entry; - uint64 expires; - void (*function)(TimerList*); - void* data; - - void init(void (*cb)(TimerList*)) { - entry.init(); - function = cb; - data = nullptr; - expires = 0; - } -}; - -extern uint64 g_jiffies; - -void timer_init(); - -// AP per-CPU initialization -void timer_init_ap(); - -// Handle timer interrupt tick (called from TrapHandler) -void timer_tick(); - -// Get configured timebase frequency -uint64 timer_get_freq(); - -void add_timer(TimerList* timer); -int del_timer(TimerList* timer); -int mod_timer(TimerList* timer, uint64 expires); diff --git a/include/lume/tlb.h b/include/lume/tlb.h deleted file mode 100644 index b4d51ea..0000000 --- a/include/lume/tlb.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * tlb.h — Machine-Independent TLB management interface - * - * All TLB invalidation in the kernel MUST go through these functions. - * Direct use of arch::mmu::flush_tlb_*() is prohibited outside of - * this file's implementation. - * - * Current implementation: local CPU sfence.vma only (single-core). - * When SMP IPI infrastructure is available, tlb_shootdown_range() - * and tlb_shootdown_all() will broadcast invalidation to remote - * CPUs via IPI — no caller changes required. - * - * Reference: docs/specs/linux_abi_mm_plan.md §4 - */ - -#include <lume/types.h> - -struct VmSpace; - -/* - * Invalidate TLB entries for a VA range [start, end) on ALL CPUs - * that may have cached translations for the given address space. - * - * @mm: address space (used to determine which CPUs to IPI; - * nullptr means kernel address space = all CPUs). - * @start: first VA to invalidate (page-aligned). - * @end: one-past-last VA to invalidate (page-aligned). - * - * If (end - start) exceeds a threshold, falls back to full flush. - */ -void tlb_shootdown_range(VmSpace* mm, uint64 start, uint64 end); - -/* - * Invalidate a single page's TLB entry on ALL CPUs. - * Convenience wrapper around tlb_shootdown_range(). - */ -void tlb_shootdown_page(VmSpace* mm, uint64 va); - -/* - * Full TLB flush on ALL CPUs. - * Used after page table switch, large-scale munmap, etc. - */ -void tlb_shootdown_all(); diff --git a/include/lume/trap.h b/include/lume/trap.h deleted file mode 100644 index 61a5054..0000000 --- a/include/lume/trap.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * Trap Subsystem — Machine-Independent Interface - * - * Defines TrapCause enum and MI-layer declarations. - * MD layer (arch/riscv/trap/trap_md.cc) translates scause → TrapCause. - * MI layer (kernel/trap.cc) dispatches based on TrapCause alone. - * - * Reference: docs/specs/trap.md §3.2 - */ - -#include <lume/types.h> - -/* MI-layer trap cause classification. - * MD layer is responsible for translating architecture-specific cause codes - * (e.g., RISC-V scause) into these semantic values. MI layer never reads CSRs. */ -enum class TrapCause : uint32 { - /* --- Exceptions (Synchronous) --- */ - PageFaultLoad = 0, // Load page fault - PageFaultStore = 1, // Store/AMO page fault - PageFaultExec = 2, // Instruction page fault - Syscall = 3, // User-mode ecall - IllegalInst = 4, // Illegal instruction - Breakpoint = 5, // Breakpoint (ebreak) - AccessFault = 6, // Bus access fault (not page fault) - AlignFault = 7, // Address misalignment - - /* --- Interrupts (Asynchronous) --- */ - IrqTimer = 16, // S-mode timer interrupt - IrqSoftware = 17, // S-mode software interrupt (IPI) - IrqExternal = 18, // S-mode external interrupt (PLIC) - - /* --- Unknown --- */ - Unknown = 255, -}; - -/* High-level trap class for routing and stats. */ -enum class TrapClass : uint8 { - Exception = 0, - Interrupt = 1, - Syscall = 2, - Unknown = 3, -}; - -/* Origin privilege of the trap. */ -enum class TrapOrigin : uint8 { - FromUser = 0, - FromKernel = 1, -}; - -/* Unified trap context passed from MD to MI. */ -struct TrapInfo { - TrapClass cls; - TrapCause cause; - TrapOrigin origin; - uint64 val; // stval (faulting address or instruction) - uint64 epc; // sepc at trap entry (may be adjusted by MD) - uint64 scause; // raw scause for diagnostics -}; - -/* Trap statistics for debugging/testing. */ -inline constexpr uint32 kTrapCauseCount = 12; - -struct TrapStats { - uint64 total; - uint64 by_cause[kTrapCauseCount]; - TrapCause last_cause; - TrapClass last_class; - TrapOrigin last_origin; - uint64 last_val; - uint64 last_epc; - uint64 last_scause; -}; - -namespace arch { -struct TrapFrame; // Forward declaration (defined in arch/trapframe.h) -} - -/* - * trap_init() — BSP initialization - * Sets stvec to kernel_trap_entry (handles traps while in S-mode). - * Initializes the global IrqManager. - * Called from kernel_main() after VMM and before PLIC. - */ -void trap_init(); - -/* - * trap_init_ap() — AP per-CPU initialization - * Sets this CPU's stvec. - */ -void trap_init_ap(); - -/* - * trap_handle() — MI-layer semantic dispatcher - * Called by MD layer after scause → TrapCause translation. - * Routes to page fault handler, syscall dispatcher, IRQ manager, etc. - * - * tf: pointer to the current TrapFrame - * info: translated trap context from MD layer - */ -void trap_handle(arch::TrapFrame* tf, const TrapInfo& info); - -/* Trap statistics helpers (MI layer). */ -void trap_stats_get(TrapStats* out); -void trap_stats_reset(); diff --git a/include/lume/tty.h b/include/lume/tty.h deleted file mode 100644 index 34cf7bb..0000000 --- a/include/lume/tty.h +++ /dev/null @@ -1,165 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * tty.h — TTY subsystem core structures - * - * tty_struct is the central object representing an open terminal. - * It connects a hardware driver (tty_driver) with a line discipline - * (tty_ldisc) to implement the full terminal abstraction. - * - * Architecture: - * user read/write → tty_core → tty_ldisc (n_tty) → tty_driver (uart/pty) - * - * Reference: Linux include/linux/tty.h, include/linux/tty_ldisc.h - */ - -#include <lume/types.h> -#include <lume/tty_ioctl.h> -#include <lume/waitqueue.h> -#include <kernel/sync/spinlock.h> - -struct tty_struct; -struct file; -struct file_operations; -struct inode; - -/* ================================================================== */ -/* tty_driver — hardware/pseudo-terminal driver interface */ -/* ================================================================== */ - -struct tty_driver_ops { - int (*open)(tty_struct* tty); - void (*close)(tty_struct* tty); - int (*write)(tty_struct* tty, const char* buf, int count); - int (*write_room)(tty_struct* tty); - void (*put_char)(tty_struct* tty, char ch); - void (*flush_chars)(tty_struct* tty); - int (*chars_in_buffer)(tty_struct* tty); - void (*flush_buffer)(tty_struct* tty); - int (*ioctl)(tty_struct* tty, unsigned int cmd, uint64 arg); - void (*throttle)(tty_struct* tty); - void (*unthrottle)(tty_struct* tty); - void (*hangup)(tty_struct* tty); -}; - -struct tty_driver { - const char* name; /* "ttyS", "ttySIF", "pts" */ - int major; - int minor_start; - int num; /* number of devices */ - const tty_driver_ops* ops; -}; - -/* ================================================================== */ -/* tty_ldisc — line discipline interface */ -/* ================================================================== */ - -struct tty_ldisc_ops { - const char* name; - int num; /* N_TTY = 0 */ - - int (*open)(tty_struct* tty); - void (*close)(tty_struct* tty); - int (*read)(tty_struct* tty, file* fp, char* buf, uint64 count); - int (*write)(tty_struct* tty, file* fp, const char* buf, uint64 count); - void (*receive_buf)(tty_struct* tty, const char* buf, int count); - int (*ioctl)(tty_struct* tty, unsigned int cmd, uint64 arg); - void (*flush_buffer)(tty_struct* tty); - int (*chars_in_buffer)(tty_struct* tty); - void (*set_termios)(tty_struct* tty, const termios* old); - void (*hangup)(tty_struct* tty); -}; - -struct tty_ldisc { - const tty_ldisc_ops* ops; - void* data; /* ldisc private data (n_tty_data*) */ -}; - -/* ================================================================== */ -/* tty_struct — central TTY object */ -/* ================================================================== */ - -inline constexpr int TTY_BUF_SIZE = 4096; - -/* TTY flags */ -inline constexpr uint32 TTY_THROTTLED = (1 << 0); -inline constexpr uint32 TTY_IO_ERROR = (1 << 1); -inline constexpr uint32 TTY_CLOSING = (1 << 2); -inline constexpr uint32 TTY_HUPPING = (1 << 3); - -struct tty_struct { - int index; /* device index */ - const tty_driver* driver; /* hardware driver */ - tty_ldisc ldisc; /* current line discipline */ - tty_struct* link; /* PTY peer (master ↔ slave) */ - - termios termios_data; /* terminal settings */ - winsize ws; /* window size */ - - int32 pgrp; /* foreground process group */ - int32 session; /* controlling session */ - - /* Output buffer (tty_core → driver) */ - char write_buf[TTY_BUF_SIZE]; - int write_cnt; - - /* Synchronization */ - WaitQueue read_wait; - WaitQueue write_wait; - Spinlock lock; - - uint32 flags; - int open_count; - - /* Private driver data */ - void* driver_data; -}; - -/* ================================================================== */ -/* TTY core API */ -/* ================================================================== */ - -/* Initialize the TTY subsystem (creates /dev/console TTY) */ -void tty_init(); - -/* Allocate and initialize a new tty_struct */ -tty_struct* tty_alloc(const tty_driver* driver, int index); - -/* Open/close a TTY (called from chardev open/close) */ -int tty_open(tty_struct* tty); -void tty_close(tty_struct* tty); - -/* Core I/O (called from file_operations) */ -int64 tty_read(tty_struct* tty, file* fp, char* buf, uint64 count); -int64 tty_write(tty_struct* tty, file* fp, const char* buf, uint64 count); -long tty_ioctl(tty_struct* tty, file* fp, unsigned int cmd, uint64 arg); - -/* Called by hardware driver when bytes arrive */ -void tty_receive_buf(tty_struct* tty, const char* buf, int count); - -/* Signal helpers */ -void tty_signal_pgrp(tty_struct* tty, int sig); - -/* file_operations for TTY devices */ -extern file_operations tty_fops; - -/* Global console TTY */ -extern tty_struct* g_console_tty; - -/* ================================================================== */ -/* N_TTY line discipline */ -/* ================================================================== */ - -extern const tty_ldisc_ops n_tty_ops; - -/* ================================================================== */ -/* UART TTY driver */ -/* ================================================================== */ - -extern const tty_driver uart_tty_driver; - -/* Initialize UART as a TTY driver (registers RX IRQ) */ -void uart_tty_init(tty_struct* tty); diff --git a/include/lume/tty_ioctl.h b/include/lume/tty_ioctl.h deleted file mode 100644 index 87ba59b..0000000 --- a/include/lume/tty_ioctl.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * tty_ioctl.h — Terminal I/O control constants and structures - * - * Linux-compatible termios, winsize, and TIOC* ioctl definitions. - * Values match the RISC-V/generic Linux ABI. - * - * Reference: include/uapi/asm-generic/termbits.h, - * include/uapi/asm-generic/ioctls.h - */ - -#include <lume/types.h> - -/* ================================================================== */ -/* termios c_cc indices */ -/* ================================================================== */ - -inline constexpr int VINTR = 0; -inline constexpr int VQUIT = 1; -inline constexpr int VERASE = 2; -inline constexpr int VKILL = 3; -inline constexpr int VEOF = 4; -inline constexpr int VTIME = 5; -inline constexpr int VMIN = 6; -inline constexpr int VSWTC = 7; -inline constexpr int VSTART = 8; -inline constexpr int VSTOP = 9; -inline constexpr int VSUSP = 10; -inline constexpr int VEOL = 11; -inline constexpr int VREPRINT = 12; -inline constexpr int VDISCARD = 13; -inline constexpr int VWERASE = 14; -inline constexpr int VLNEXT = 15; -inline constexpr int VEOL2 = 16; -inline constexpr int NCCS = 19; - -/* ================================================================== */ -/* c_iflag — input mode flags */ -/* ================================================================== */ - -inline constexpr uint32 IGNBRK = 0000001; -inline constexpr uint32 BRKINT = 0000002; -inline constexpr uint32 IGNPAR = 0000004; -inline constexpr uint32 PARMRK = 0000010; -inline constexpr uint32 INPCK = 0000020; -inline constexpr uint32 ISTRIP = 0000040; -inline constexpr uint32 INLCR = 0000100; -inline constexpr uint32 IGNCR = 0000200; -inline constexpr uint32 ICRNL = 0000400; -inline constexpr uint32 IUCLC = 0001000; -inline constexpr uint32 IXON = 0002000; -inline constexpr uint32 IXANY = 0004000; -inline constexpr uint32 IXOFF = 0010000; -inline constexpr uint32 IMAXBEL = 0020000; -inline constexpr uint32 IUTF8 = 0040000; - -/* ================================================================== */ -/* c_oflag — output mode flags */ -/* ================================================================== */ - -inline constexpr uint32 OPOST = 0000001; -inline constexpr uint32 OLCUC = 0000002; -inline constexpr uint32 ONLCR = 0000004; -inline constexpr uint32 OCRNL = 0000010; -inline constexpr uint32 ONOCR = 0000020; -inline constexpr uint32 ONLRET = 0000040; -inline constexpr uint32 OFILL = 0000100; -inline constexpr uint32 OFDEL = 0000200; - -/* ================================================================== */ -/* c_cflag — control mode flags */ -/* ================================================================== */ - -inline constexpr uint32 CSIZE = 0000060; -inline constexpr uint32 CS5 = 0000000; -inline constexpr uint32 CS6 = 0000020; -inline constexpr uint32 CS7 = 0000040; -inline constexpr uint32 CS8 = 0000060; -inline constexpr uint32 CSTOPB = 0000100; -inline constexpr uint32 CREAD = 0000200; -inline constexpr uint32 PARENB = 0000400; -inline constexpr uint32 PARODD = 0001000; -inline constexpr uint32 HUPCL = 0002000; -inline constexpr uint32 CLOCAL = 0004000; - -/* Baud rates (stored in c_cflag masked with CBAUD) */ -inline constexpr uint32 CBAUD = 0010017; -inline constexpr uint32 B0 = 0000000; -inline constexpr uint32 B9600 = 0000015; -inline constexpr uint32 B19200 = 0000016; -inline constexpr uint32 B38400 = 0000017; -inline constexpr uint32 B115200 = 0010002; - -/* ================================================================== */ -/* c_lflag — local mode flags */ -/* ================================================================== */ - -inline constexpr uint32 ISIG = 0000001; -inline constexpr uint32 ICANON = 0000002; -inline constexpr uint32 XCASE = 0000004; -inline constexpr uint32 LECHO = 0000010; /* Named LECHO to avoid macro conflict */ -inline constexpr uint32 ECHOE = 0000020; -inline constexpr uint32 ECHOK = 0000040; -inline constexpr uint32 ECHONL = 0000100; -inline constexpr uint32 NOFLSH = 0000200; -inline constexpr uint32 TOSTOP = 0000400; -inline constexpr uint32 ECHOCTL = 0001000; -inline constexpr uint32 ECHOPRT = 0002000; -inline constexpr uint32 ECHOKE = 0004000; -inline constexpr uint32 IEXTEN = 0100000; - -/* Linux uses ECHO = 0x0008, we use LECHO to avoid reserved-name issues. - * Provide the standard name as well for ioctl compatibility. */ -inline constexpr uint32 ECHO = LECHO; - -/* ================================================================== */ -/* termios structure */ -/* ================================================================== */ - -struct termios { - uint32 c_iflag; /* input mode flags */ - uint32 c_oflag; /* output mode flags */ - uint32 c_cflag; /* control mode flags */ - uint32 c_lflag; /* local mode flags */ - uint8 c_line; /* line discipline */ - uint8 c_cc[NCCS]; /* control characters */ -}; - -/* ================================================================== */ -/* winsize structure */ -/* ================================================================== */ - -struct winsize { - uint16 ws_row; - uint16 ws_col; - uint16 ws_xpixel; - uint16 ws_ypixel; -}; - -/* ================================================================== */ -/* ioctl command numbers (Linux asm-generic/ioctls.h) */ -/* ================================================================== */ - -inline constexpr uint32 TCGETS = 0x5401; -inline constexpr uint32 TCSETS = 0x5402; -inline constexpr uint32 TCSETSW = 0x5403; -inline constexpr uint32 TCSETSF = 0x5404; -inline constexpr uint32 TCGETA = 0x5405; -inline constexpr uint32 TCSETA = 0x5406; -inline constexpr uint32 TCSETAW = 0x5407; -inline constexpr uint32 TCSETAF = 0x5408; -inline constexpr uint32 TCSBRK = 0x5409; -inline constexpr uint32 TCXONC = 0x540A; -inline constexpr uint32 TCFLSH = 0x540B; -inline constexpr uint32 TIOCEXCL = 0x540C; -inline constexpr uint32 TIOCNXCL = 0x540D; -inline constexpr uint32 TIOCSCTTY = 0x540E; -inline constexpr uint32 TIOCGPGRP = 0x540F; -inline constexpr uint32 TIOCSPGRP = 0x5410; -inline constexpr uint32 TIOCOUTQ = 0x5411; -inline constexpr uint32 TIOCSTI = 0x5412; -inline constexpr uint32 TIOCGWINSZ = 0x5413; -inline constexpr uint32 TIOCSWINSZ = 0x5414; -inline constexpr uint32 TIOCMGET = 0x5415; -inline constexpr uint32 TIOCMSET = 0x5418; -inline constexpr uint32 FIONREAD = 0x541B; -inline constexpr uint32 TIOCNOTTY = 0x5422; -inline constexpr uint32 TIOCGPTLCK = 0x80045430; -inline constexpr uint32 TIOCSPTLCK = 0x40045431; - -/* Default termios for a new TTY */ -inline void tty_default_termios(termios* t) -{ - t->c_iflag = ICRNL | IXON | IUTF8; - t->c_oflag = OPOST | ONLCR; - t->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; - t->c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN; - t->c_line = 0; /* N_TTY */ - - for (int i = 0; i < NCCS; i++) - t->c_cc[i] = 0; - - t->c_cc[VINTR] = 003; /* Ctrl+C */ - t->c_cc[VQUIT] = 034; /* Ctrl+\ */ - t->c_cc[VERASE] = 0177; /* DEL */ - t->c_cc[VKILL] = 025; /* Ctrl+U */ - t->c_cc[VEOF] = 004; /* Ctrl+D */ - t->c_cc[VSTART] = 021; /* Ctrl+Q */ - t->c_cc[VSTOP] = 023; /* Ctrl+S */ - t->c_cc[VSUSP] = 032; /* Ctrl+Z */ - t->c_cc[VREPRINT] = 022; /* Ctrl+R */ - t->c_cc[VWERASE] = 027; /* Ctrl+W */ - t->c_cc[VLNEXT] = 026; /* Ctrl+V */ - t->c_cc[VEOL] = 0; - t->c_cc[VEOL2] = 0; - t->c_cc[VMIN] = 1; - t->c_cc[VTIME] = 0; -} diff --git a/include/lume/types.h b/include/lume/types.h deleted file mode 100644 index 2342359..0000000 --- a/include/lume/types.h +++ /dev/null @@ -1,78 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#ifndef _LUME_TYPES_H -#define _LUME_TYPES_H - -/* - * LumeOS Base Type Definitions - * - * Three naming layers coexist so that source files imported from - * upstream projects (Linux kernel, libfdt) compile unchanged: - * - * LumeOS native uint8 / int8 / ... / uint64 / int64 - * Linux kernel short names u8 / s8 / ... / u64 / s64 - * POSIX / C99 (with _t) uint8_t / ... / uint64_t / intptr_t - * - * All three resolve to the same underlying compiler builtin, so they - * are binary-compatible. - * - * Declared with C `typedef` (not C++ `using`) so this header may be - * included from .c sources — required for libfdt shims and the - * arch/riscv/kernel/pi/ subsystem, which are pure C imports from - * Linux. C++ accepts `typedef` syntax identically. - */ - -/* ===== LumeOS native names ===== */ -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; -typedef unsigned long long uint64; - -typedef signed char int8; -typedef signed short int16; -typedef signed int int32; -typedef signed long long int64; - -typedef __SIZE_TYPE__ size_t; -typedef __PTRDIFF_TYPE__ ptrdiff_t; -typedef int64 ssize_t; -typedef uint64 uintptr; - -/* ===== Linux kernel short names ===== */ -typedef uint8 u8; typedef int8 s8; -typedef uint16 u16; typedef int16 s16; -typedef uint32 u32; typedef int32 s32; -typedef uint64 u64; typedef int64 s64; - -/* ===== POSIX / C99 aliases ===== - * Guarded so a later #include <stdint.h> from libc-shim during musl - * userspace builds is a no-op rather than a redefinition error. */ -#ifndef _STDINT_H -# define _STDINT_H -typedef uint8 uint8_t; -typedef uint16 uint16_t; -typedef uint32 uint32_t; -typedef uint64 uint64_t; -typedef int8 int8_t; -typedef int16 int16_t; -typedef int32 int32_t; -typedef int64 int64_t; -typedef uintptr uintptr_t; -typedef int64 intptr_t; -#endif - -/* ===== Linux domain typedefs needed by RISC-V boot path ===== */ -typedef uint64 phys_addr_t; - -/* ===== libfdt on-wire types (big-endian). Real byte-swap helpers - * live in <lume/libfdt_env.h>. ===== */ -typedef uint16 fdt16_t; -typedef uint32 fdt32_t; -typedef uint64 fdt64_t; - -#ifndef offsetof -# define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) -#endif - -#endif /* _LUME_TYPES_H */ diff --git a/include/lume/uaccess.h b/include/lume/uaccess.h deleted file mode 100644 index 5a9ed71..0000000 --- a/include/lume/uaccess.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * User-space memory access — safe copy routines. - * - * Phase 2: Software page-table validation. - * Phase 3+: Exception Table (zero-cost happy path). - * - * Reference: docs/specs/syscall.md §8 - */ - -#include <lume/types.h> - -/* Copy len bytes from user address to kernel buffer. - * Returns 0 on success, -EFAULT if user address is invalid. */ -int copy_from_user(void* kernel_dst, uint64 user_src, uint64 len); - -/* Copy len bytes from kernel buffer to user address. - * Returns 0 on success, -EFAULT if user address is invalid. */ -int copy_to_user(uint64 user_dst, const void* kernel_src, uint64 len); - -/* Copy NUL-terminated string from user space. - * Returns string length (excluding NUL) or -EFAULT. */ -int64 strncpy_from_user(char* kernel_dst, uint64 user_src, uint64 max_len); diff --git a/include/lume/uuid.h b/include/lume/uuid.h deleted file mode 100644 index fcbd4a3..0000000 --- a/include/lume/uuid.h +++ /dev/null @@ -1,207 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * UUID/GUID definition - * - * Copyright (C) 2010, 2016 Intel Corp. - * Huang Ying <ying.huang@intel.com> - */ - -#pragma once - -#include <lume/types.h> -#include <libc-shim/string.h> - -constexpr uint32 UUID_SIZE = 16; -constexpr uint32 UUID_STRING_LEN = 36; - -static inline int uuid_hex_value(char c) -{ - if (c >= '0' && c <= '9') { - return c - '0'; - } - if (c >= 'a' && c <= 'f') { - return c - 'a' + 10; - } - if (c >= 'A' && c <= 'F') { - return c - 'A' + 10; - } - return -1; -} - -static inline bool uuid_parse_raw(const char* uuid, uint8 out[UUID_SIZE]) -{ - if (!uuid) { - return false; - } - if (strlen(uuid) != UUID_STRING_LEN) { - return false; - } - if (uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-') { - return false; - } - - int out_index = 0; - for (int i = 0; i < static_cast<int>(UUID_STRING_LEN); ) { - if (uuid[i] == '-') { - ++i; - continue; - } - - int hi = uuid_hex_value(uuid[i]); - int lo = uuid_hex_value(uuid[i + 1]); - if (hi < 0 || lo < 0) { - return false; - } - - out[out_index++] = static_cast<uint8>((hi << 4) | lo); - i += 2; - } - - return out_index == static_cast<int>(UUID_SIZE); -} - -struct uuid_base { - uint8 b[UUID_SIZE]; - - bool is_null() const - { - for (uint32 i = 0; i < UUID_SIZE; ++i) { - if (b[i] != 0) { - return false; - } - } - return true; - } - - bool operator==(const uuid_base& other) const - { - return memcmp(b, other.b, UUID_SIZE) == 0; - } - - bool operator!=(const uuid_base& other) const - { - return !(*this == other); - } -}; - -struct uuid_t : public uuid_base { - explicit uuid_t(const uint8 in_b[UUID_SIZE]) - { - memcpy(b, in_b, UUID_SIZE); - } - - explicit constexpr uuid_t(uint32 a, uint16 b, uint16 c, uint8 d0, uint8 d1, - uint8 d2, uint8 d3, uint8 d4, uint8 d5, - uint8 d6, uint8 d7) - : uuid_base{{ - static_cast<uint8>((a >> 24) & 0xff), - static_cast<uint8>((a >> 16) & 0xff), - static_cast<uint8>((a >> 8) & 0xff), - static_cast<uint8>(a & 0xff), - static_cast<uint8>((b >> 8) & 0xff), - static_cast<uint8>(b & 0xff), - static_cast<uint8>((c >> 8) & 0xff), - static_cast<uint8>(c & 0xff), - d0, d1, d2, d3, d4, d5, d6, d7 - }} - { - } - - constexpr uuid_t() : uuid_base{{0}} {} - - static bool parse(const char* uuid, uuid_t& out) - { - uint8 tmp[UUID_SIZE]; - if (!uuid_parse_raw(uuid, tmp)) { - return false; - } - - memcpy(out.b, tmp, UUID_SIZE); - return true; - } - - static bool is_valid(const char* uuid) - { - uint8 tmp[UUID_SIZE]; - return uuid_parse_raw(uuid, tmp); - } - - static constexpr uuid_t null() - { - return uuid_t(); - } - - void import_bytes(const uint8* src) - { - memcpy(b, src, UUID_SIZE); - } - - void export_bytes(uint8* dst) const - { - memcpy(dst, b, UUID_SIZE); - } -}; - -struct guid_t : public uuid_base { - explicit guid_t(const uint8 in_b[UUID_SIZE]) - { - memcpy(b, in_b, UUID_SIZE); - } - - explicit constexpr guid_t(uint32 a, uint16 b, uint16 c, uint8 d0, uint8 d1, - uint8 d2, uint8 d3, uint8 d4, uint8 d5, - uint8 d6, uint8 d7) - : uuid_base{{ - static_cast<uint8>(a & 0xff), - static_cast<uint8>((a >> 8) & 0xff), - static_cast<uint8>((a >> 16) & 0xff), - static_cast<uint8>((a >> 24) & 0xff), - static_cast<uint8>(b & 0xff), - static_cast<uint8>((b >> 8) & 0xff), - static_cast<uint8>(c & 0xff), - static_cast<uint8>((c >> 8) & 0xff), - d0, d1, d2, d3, d4, d5, d6, d7 - }} - { - } - - constexpr guid_t() : uuid_base{{0}} {} - static bool parse(const char* uuid, guid_t& out) - { - uint8 tmp[UUID_SIZE]; - if (!uuid_parse_raw(uuid, tmp)) { - return false; - } - - static constexpr uint8 guid_index[UUID_SIZE] = { - 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15, - }; - - for (int i = 0; i < static_cast<int>(UUID_SIZE); ++i) { - out.b[guid_index[i]] = tmp[i]; - } - return true; - } - - static bool is_valid(const char* uuid) - { - uint8 tmp[UUID_SIZE]; - return uuid_parse_raw(uuid, tmp); - } - - static constexpr guid_t null() - { - return guid_t(); - } - - void import_bytes(const uint8* src) - { - memcpy(b, src, UUID_SIZE); - } - - void export_bytes(uint8* dst) const - { - memcpy(dst, b, UUID_SIZE); - } -}; - diff --git a/include/lume/vmm.h b/include/lume/vmm.h deleted file mode 100644 index 9cbebf1..0000000 --- a/include/lume/vmm.h +++ /dev/null @@ -1,115 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * vmm.h — Virtual Memory Manager - * - * Managing kernel and user virtual address spaces. - * - * Reference: docs/specs/vmm.md - */ - -#include <lume/types.h> -#include <lume/rbtree.h> -#include <lume/atomic.h> -#include <kernel/sync/spinlock.h> - -/* ------------------------------------------------------------------ */ -/* MI-layer permission flags (architecture-independent) */ -/* */ -/* These are used by VMA and vmm_map_user / vmm_handle_page_fault. */ -/* The pmap MD layer translates them to hardware PTE bits. */ -/* ------------------------------------------------------------------ */ -inline constexpr uint64 VM_READ = (1ULL << 0); -inline constexpr uint64 VM_WRITE = (1ULL << 1); -inline constexpr uint64 VM_EXEC = (1ULL << 2); -inline constexpr uint64 VM_USER = (1ULL << 3); - -enum class VmFaultCause : uint8 { - Read = 0, - Write = 1, - Exec = 2, -}; - -/* Forward declarations */ -struct VmSpace; -struct VmAreaStruct; - -/* - * Virtual Memory Area (VMA) - * Represents a contiguous range [start, end) of uniform permissions. - */ -struct VmAreaStruct { - uint64 start; // Start VA (page aligned) - uint64 end; // End VA (exclusive, page aligned) - uint64 perm; // VM_READ | VM_WRITE | VM_EXEC | VM_USER - struct rb_node rb; // Linkage in VmSpace::vma_tree - VmSpace* mm; // Back pointer to the parent address space -}; - -/* - * Address Space (VmSpace) - * Represents a user process's complete virtual memory mapping. - * - * Lock contract: - * Holds: lock (internal spinlock) - * May acquire: PMM global lock (via pmm_alloc_page inside page fault) - * Callers must NOT hold: PMM lock (lock ordering: VmSpace -> PMM) - */ -struct VmSpace { - uint64 root_pa; // SV39 root page table physical address - struct rb_root vma_tree; // Red-black tree of VmAreaStructs - Spinlock lock; // Protects vma_tree mutations - lume::atomic<int32> refcount; // Reference count (for CLONE_VM sharing) - lume::atomic<uint64> cpu_mask; // Bitmask of CPUs with this mm in satp - - uint64 brk_start; // Start of heap (page-aligned) - uint64 brk_end; // Current heap end (page-aligned) - uint64 mmap_base; // Base for mmap (Linux: TASK_UNMAPPED_BASE = TASK_SIZE/3) - - // Create a brand new VmSpace (allocates root pagetable, refcount=1) - static VmSpace* create(); - - // Increment reference count (for CLONE_VM) - void incref(); - - // Decrement reference count; destroys VmSpace when it reaches 0. - // Call this instead of destroy() directly. - void put(); - - // Destroy VmSpace, unmapping all VMAs and freeing pagetables. - // Internal — called by put() when refcount drops to 0. - void destroy(); -}; - -/* Initialize kernel page table (Phase 1) */ -void vmm_init(); - -/* Switch AP to the kernel page table built by BSP (Phase 1) */ -void vmm_init_ap(); - -/* Map MMIO device region to the active kernel page table */ -void vmm_map_kernel_mmio(uint64 pa, uint64 size); - -/* Query page_map allocation (set by vmm_init, read by pmm_init). - * Returns the PA, byte size, and page count of the vmemmap region. */ -uint64 vmm_get_page_map_pa(); -uint64 vmm_get_page_map_size(); -uint64 vmm_get_num_pages(); - -/* User space memory management (VMA & Demand Paging) */ -int vmm_map_user(VmSpace* space, uint64 va, uint64 len, uint64 perm); -int vmm_unmap_user(VmSpace* space, uint64 va, uint64 len); -int vmm_protect_user(VmSpace* space, uint64 va, uint64 len, uint64 perm); - -/* VMA helpers for mmap/mprotect implementations */ -uint64 mm_find_free_va(VmSpace* space, uint64 length, uint64 align); -bool vma_range_covered(VmSpace* space, uint64 start, uint64 end); - -/* Handle user page fault (lookup VMA -> allocate page -> map) */ -int vmm_handle_page_fault(VmSpace* space, uint64 fault_addr, VmFaultCause cause); - -/* Clone an address space for fork() */ -VmSpace* vmm_clone(VmSpace* parent_space); diff --git a/include/lume/wait.h b/include/lume/wait.h deleted file mode 100644 index 865c1f2..0000000 --- a/include/lume/wait.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * POSIX waitpid / wait4 Constants - * Reference: docs/specs/syscall.md §9 - */ - -/* waitpid options */ -inline constexpr int WNOHANG = 1; -inline constexpr int WUNTRACED = 2; -inline constexpr int WCONTINUED = 8; -inline constexpr int WSTOPPED = WUNTRACED; /* POSIX alias */ -inline constexpr int WEXITED = 4; /* POSIX */ -inline constexpr int WNOWAIT = 0x01000000; /* POSIX: peek, don't reap */ - -/* Exit status encoding (Linux-compatible) */ -static inline int WEXITSTATUS(int s) { return (s >> 8) & 0xFF; } -static inline bool WIFEXITED(int s) { return (s & 0x7F) == 0; } -static inline bool WIFSIGNALED(int s) { return (s & 0x7F) != 0 && (s & 0x7F) != 0x7F; } -static inline int WTERMSIG(int s) { return s & 0x7F; } -static inline bool WIFSTOPPED(int s) { return (s & 0xFF) == 0x7F; } -static inline int WSTOPSIG(int s) { return (s >> 8) & 0xFF; } -static inline bool WIFCONTINUED(int s){ return s == 0xFFFF; } - -/* Encode exit code into wstatus (normal exit) */ -static inline int W_EXITCODE(int code) { return (code & 0xFF) << 8; } -static inline int W_STOPCODE(int sig) { return ((sig & 0xFF) << 8) | 0x7F; } -static inline int W_CONTINUED() { return 0xFFFF; } diff --git a/include/lume/waitqueue.h b/include/lume/waitqueue.h deleted file mode 100644 index 3720cb7..0000000 --- a/include/lume/waitqueue.h +++ /dev/null @@ -1,79 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* Copyright (C) 2026 Richard Qin */ - -#pragma once - -/* - * WaitQueue — blocking synchronization primitive - * - * Supports two usage patterns: - * - * 1. Simple (legacy): wq.sleep() — combines prepare/schedule/finish. - * Suitable for simple cases where no external condition is checked. - * - * 2. Linux-style two-phase (recommended for correctness): - * - * wq.prepare_to_wait(curr, TaskState::Sleeping); - * if (!condition) { - * schedule(); - * } - * wq.finish_wait(curr); - * - * This pattern prevents the "lost wakeup" race: the task is already - * on the wait list (and marked Sleeping) BEFORE checking the condition. - * If a wake_one/wake_all fires between the check and schedule(), the - * task's state will already be set back to Runnable, and schedule() - * will see state == Runnable and simply re-run the task. - * - * Reference: docs/specs/scheduler.md, docs/specs/task.md §5 - */ - -#include <lume/types.h> -#include <lume/list.h> -#include <kernel/sync/spinlock.h> - -struct TaskControlBlock; -enum class TaskState : uint8; - -class WaitQueue { -public: - void init(const char* name = "wq") { - head_.init(); - lock_.init(name); - } - - /* - * Phase 1: Add the task to the wait queue and set its state. - * The task is NOT yet descheduled — the caller must check the - * condition and call schedule() if the condition is still false. - * - * Must be called with interrupts disabled or preemption disabled. - */ - void prepare_to_wait(TaskControlBlock* task, TaskState new_state); - - /* - * Phase 3: Remove the task from the wait queue (if still on it) - * and ensure its state is Runnable. Called after schedule() returns - * (i.e. after the task has been woken up, or if the condition was - * true and schedule() was skipped). - */ - void finish_wait(TaskControlBlock* task); - - /* Legacy convenience: combines prepare_to_wait + schedule + finish_wait. - * If external_lock is provided, it is released AFTER the task is - * added to the wait queue but BEFORE schedule() is called. */ - void sleep(Spinlock* external_lock = nullptr); - - /* Wake the first (oldest) sleeping task. Returns true if a task was woken. */ - bool wake_one(); - - /* Wake all sleeping tasks. Returns the number of tasks woken. */ - int wake_all(); - - /* Check if any tasks are waiting. */ - bool is_empty() const { return head_.is_empty(); } - -private: - list_node head_; - Spinlock lock_; -}; diff --git a/include/zircon/LICENSE b/include/zircon/LICENSE deleted file mode 100644 index 7ed244f..0000000 --- a/include/zircon/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright 2019 The Fuchsia Authors. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/include/zircon/README.lume b/include/zircon/README.lume deleted file mode 100644 index 41e610f..0000000 --- a/include/zircon/README.lume +++ /dev/null @@ -1,11 +0,0 @@ -Zircon public support headers required by the first kernel library batch - -Fuchsia revision: f8d670ab4bbb71bfb4d569893ba12fbb8a83bacd - -Imported files: - zircon/system/public/zircon/compiler.h - sdk/lib/zircon-assert/zircon/assert.h - -The assert header is a regular-file copy of the SDK target. The corresponding -path under zircon/system/public is a Fuchsia-tree-relative symbolic link and -is deliberately not reproduced as a broken link. diff --git a/include/zircon/assert.h b/include/zircon/assert.h deleted file mode 100644 index 47f8c4d..0000000 --- a/include/zircon/assert.h +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2016 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef LIB_ZIRCON_ASSERT_ZIRCON_ASSERT_H_ -#define LIB_ZIRCON_ASSERT_ZIRCON_ASSERT_H_ - -// For a description of which asserts are enabled at which debug levels, see the documentation for -// GN build argument |assert_level|. - -#ifdef _KERNEL -#include <assert.h> -#define ZX_PANIC(args...) PANIC(args) -#define ZX_ASSERT(args...) ASSERT(args) -#define ZX_ASSERT_MSG(args...) ASSERT_MSG(args) -#define ZX_DEBUG_ASSERT(args...) DEBUG_ASSERT(args) -#define ZX_DEBUG_ASSERT_MSG(args...) DEBUG_ASSERT_MSG(args) -#define ZX_DEBUG_ASSERT_COND(args...) DEBUG_ASSERT_COND(args) -#define ZX_DEBUG_ASSERT_MSG_COND(args...) DEBUG_ASSERT_MSG_COND(args) -#define ZX_DEBUG_ASSERT_IMPLEMENTED DEBUG_ASSERT_IMPLEMENTED - -#else // #ifdef _KERNEL - -#include <zircon/compiler.h> - -__BEGIN_CDECLS -// NOLINTNEXTLINE(bugprone-reserved-identifier) -void __zx_panic(const char* format, ...) __NO_RETURN __PRINTFLIKE(1, 2); -__END_CDECLS - -#define ZX_PANIC(fmt, ...) __zx_panic((fmt), ##__VA_ARGS__) - -// Conditionally implement ZX_DEBUG_ASSERT based on ZX_ASSERT_LEVEL. -// -// ZX_DEBUG_ASSERT_IMPLEMENTED is intended to be used to conditionalize code -// that is logically part of a debug assert. It's useful for performing complex -// consistency checks that are difficult to work into a ZX_DEBUG_ASSERT -// statement. -#ifdef ZX_ASSERT_LEVEL -#define ZX_DEBUG_ASSERT_IMPLEMENTED (ZX_ASSERT_LEVEL > 1) -#else -#define ZX_DEBUG_ASSERT_IMPLEMENTED 0 -#endif - -// Notes about the C++ and C versions of the assert macros. -// -// The C++ versions of these macros follow a very specific form for testing the -// assert predicate `x`. Specifically, the test of the predicate is _always_ -// written simply as `if (x)`. Not: -// -// 1) `if (!x)` // or -// 2) `if ((x))` // or -// 3) `if (unlikely(!(x))) // or -// 4) `if (ZX_DEBUG_ASSERT_ENABLED && unlikely(!(x))) // or, anything else. -// -// It is *always* just `if (x)`. There is a method to this madness. The -// primary reason for this is to catch mistakes of the following form: -// -// ZX_DEBUG_ASSERT(my_bool_variable = false); -// ZX_ASSERT(my_int_variable = 5); -// -// Both of these are examples of a pattern where a code author meant to use -// comparison (`==`), but accidentally used assignment (`=`), meaning that the -// first of these examples is always going to fire, while the second will never -// fire. Both of them will have a side effect of mutating their variable, but a -// ZX_DEBUG_ASSERT's mutation will drop out of a release build. -// -// :: Accidental Assignment Protection :: -// -// This is all very bad, and _should_ be caught by the -Wparentheses warning, -// when enabled (which it usually is). Unfortunately, surrounding an assignment -// operation in a set of `()` will suppress the warning. Pretty much any other -// form of the predicate test ends up requiring that we add in an extra pair of -// `()`. This also includes wrapping the predicate in things like `unlikely(x)` -// and `likely(x)`. So, we have to restrict ourselves strictly to testing with -// `if (x)` in order to get the accidental assignment protection we desire. -// -// :: Temporary Variable Latching :: -// -// A surprise advantage to taking this approach is that it allows us (in C++) to -// more easily write predicates which involve latching to a temporary variable. -// Consider a case where we want to debug assert something about a value -// returned by a function which is expensive to call. We could write: -// -// DEBUG_ASSERT_MSG(Expensive() == 5, -// "Expensive() returned a non-five value (%u)", -// Expensive()); -// -// But now we are calling the expensive function twice. We could also say: -// -// [[maybe_unused]] const uint32_t e = Expensive(); -// ZX_DEBUG_ASSERT_MSG(e, "Expensive() returned a non-five value (%u)", e); -// -// but it takes a couple of lines, we have to add in a [[maybe_unused]] -// annotation, and we may still be forced to evaluate Expensive if the compiler -// cannot tell that it is guaranteed to have no side effects. -// -// With the new only-`if (x)` form of testing the predicate, however, we can do -// better. Now, we can write: -// -// ZX_DEBUG_ASSERT_MSG(const uint32_t e = Expensive(); e == 5, -// "Expensive() returned a non-five value (%u)", e); -// -// We still get our protection against accidental assignment, we are guaranteed -// to evaluate Expensive exactly once in a debug build, and zero times in a -// release build. -// -// :: WARNING - C code does not get these benefits :: -// -// To write in this style, but also preserve the likely/unlikely hinting -// benefits, we are forced to use C++'s standardized attributes `[[likely]]` and -// `[[unlikely]]``. These are not available in C, which has to use the old -// compiler attribute macros, which always end up introducing `()`, and -// suppressing the accidental assignment protection. Right now, there is no -// good way around this, and as long as we are building C code using this -// header, we will need to maintain a version of these macros which do not offer -// the same level of protection. -// -#ifdef __cplusplus - -// Only use the [[likely]] attribute if we are sure the compiler is going to -// understand it. -#if defined(__has_cpp_attribute) && (__has_cpp_attribute(likely) >= 201803L) -// NOLINTNEXTLINE(bugprone-reserved-identifier) -#define _ZIRCON_ASSERT_ATTRIBUTE_LIKELY [[likely]] -#else -// NOLINTNEXTLINE(bugprone-reserved-identifier) -#define _ZIRCON_ASSERT_ATTRIBUTE_LIKELY -#endif - -// Assert that |x| is true, else panic. -// -// ZX_ASSERT is always enabled and |x| will be evaluated regardless of any build arguments. -#define ZX_ASSERT(x) \ - do { \ - if (x) \ - _ZIRCON_ASSERT_ATTRIBUTE_LIKELY { break; } \ - else { /* NOLINT(readability-else-after-return) */ \ - ZX_PANIC("ASSERT FAILED at (%s:%d): %s", __FILE__, __LINE__, #x); \ - } \ - } while (0) - -// Assert that |x| is true, else panic with the given message. -// -// ZX_ASSERT_MSG is always enabled and |x| will be evaluated regardless of any build arguments. -#define ZX_ASSERT_MSG(x, msg, msgargs...) \ - do { \ - if (x) \ - _ZIRCON_ASSERT_ATTRIBUTE_LIKELY { break; } \ - else { \ - ZX_PANIC("ASSERT FAILED at (%s:%d): %s" msg, __FILE__, __LINE__, #x, ##msgargs); \ - } \ - } while (0) - -// Assert that |x| is true, else panic. -// -// Depending on build arguments, ZX_DEBUG_ASSERT may or may not be enabled. When disabled, |x| will -// not be evaluated. -#define ZX_DEBUG_ASSERT(x) \ - do { \ - if (ZX_DEBUG_ASSERT_IMPLEMENTED) { \ - if (x) \ - _ZIRCON_ASSERT_ATTRIBUTE_LIKELY { break; } \ - else { \ - ZX_PANIC("DEBUG ASSERT FAILED at (%s:%d): %s", __FILE__, __LINE__, #x); \ - } \ - } \ - } while (0) - -// Assert that |x| is true, else panic with the given message. -// -// Depending on build arguments, ZX_DEBUG_ASSERT_MSG may or may not be enabled. When disabled, |x| -// will not be evaluated. -#define ZX_DEBUG_ASSERT_MSG(x, msg, msgargs...) \ - do { \ - if (ZX_DEBUG_ASSERT_IMPLEMENTED) { \ - if (x) \ - _ZIRCON_ASSERT_ATTRIBUTE_LIKELY { break; } \ - else { \ - ZX_PANIC("DEBUG ASSERT FAILED at (%s:%d): %s" msg, __FILE__, __LINE__, #x, ##msgargs); \ - } \ - } \ - } while (0) - -#else // #ifdef __cplusplus - -// Assert that |x| is true, else panic. -// -// ZX_ASSERT is always enabled and |x| will be evaluated regardless of any build arguments. -#define ZX_ASSERT(x) \ - do { \ - if (unlikely(!(x))) { \ - ZX_PANIC("ASSERT FAILED at (%s:%d): %s", __FILE__, __LINE__, #x); \ - } \ - } while (0) - -// Assert that |x| is true, else panic with the given message. -// -// ZX_ASSERT_MSG is always enabled and |x| will be evaluated regardless of any build arguments. -#define ZX_ASSERT_MSG(x, msg, msgargs...) \ - do { \ - if (unlikely(!(x))) { \ - ZX_PANIC("ASSERT FAILED at (%s:%d): %s" msg, __FILE__, __LINE__, #x, ##msgargs); \ - } \ - } while (0) - -// Assert that |x| is true, else panic. -// -// Depending on build arguments, ZX_DEBUG_ASSERT may or may not be enabled. When disabled, |x| will -// not be evaluated. -#define ZX_DEBUG_ASSERT(x) \ - do { \ - if (ZX_DEBUG_ASSERT_IMPLEMENTED && unlikely(!(x))) { \ - ZX_PANIC("DEBUG ASSERT FAILED at (%s:%d): %s", __FILE__, __LINE__, #x); \ - } \ - } while (0) - -// Assert that |x| is true, else panic with the given message. -// -// Depending on build arguments, ZX_DEBUG_ASSERT_MSG may or may not be enabled. When disabled, |x| -// will not be evaluated. -#define ZX_DEBUG_ASSERT_MSG(x, msg, msgargs...) \ - do { \ - if (ZX_DEBUG_ASSERT_IMPLEMENTED && unlikely(!(x))) { \ - ZX_PANIC("DEBUG ASSERT FAILED at (%s:%d): %s" msg, __FILE__, __LINE__, #x, ##msgargs); \ - } \ - } while (0) - -#endif // #ifdef __cplusplus - // -// implement _COND versions of ZX_DEBUG_ASSERT which only emit the body if -// ZX_DEBUG_ASSERT_IMPLEMENTED is set -#if ZX_DEBUG_ASSERT_IMPLEMENTED -#define ZX_DEBUG_ASSERT_COND(x) ZX_DEBUG_ASSERT(x) -#define ZX_DEBUG_ASSERT_MSG_COND(x, msg, msgargs...) ZX_DEBUG_ASSERT_MSG(x, msg, msgargs) -#else -#define ZX_DEBUG_ASSERT_COND(x) \ - do { \ - } while (0) -#define ZX_DEBUG_ASSERT_MSG_COND(x, msg, msgargs...) \ - do { \ - } while (0) -#endif - -#endif // #ifdef _KERNEL -#endif // LIB_ZIRCON_ASSERT_ZIRCON_ASSERT_H_ diff --git a/include/zircon/compiler.h b/include/zircon/compiler.h deleted file mode 100644 index 45ea8d6..0000000 --- a/include/zircon/compiler.h +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright 2016 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file provides macros for unifying differences in C/C++ compiler -// extensions, and providing backwards-compatibility for older C++ standards. -// -// May be included by C, C++, and assembly files. - -#ifndef ZIRCON_COMPILER_H_ -#define ZIRCON_COMPILER_H_ - -// Ensure we are using a known compiler. -#if !defined(__GNUC__) && !defined(__clang__) -#error "Unrecognized compiler!" -#endif - -// Feature checking macros. -// -// If feature checking macros are not provided by the compiler, we assume that the -// checked features are unavailable. - -// C++11 attribute checking. -#ifndef __has_cpp_attribute -#define __has_cpp_attribute(x) 0 -#endif - -// clang feature checking. -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -#if !defined(__ASSEMBLER__) - -// C++ header guards. -#ifdef __cplusplus -#define __BEGIN_CDECLS extern "C" { -#define __END_CDECLS } -#else -#define __BEGIN_CDECLS -#define __END_CDECLS -#endif - -// -// Function and data attributes. -// - -// Function inlining directives. -#define __NO_INLINE __attribute__((__noinline__)) -#define __ALWAYS_INLINE __attribute__((__always_inline__)) - -// Avoid issuing a warning if the given variable/function is unused. -#ifndef __cplusplus -#define __UNUSED __attribute__((__unused__)) -#endif - -// Pack the given structure or class, omitting padding between fields. -#define __PACKED __attribute__((packed)) - -// Place the variable in thread-local storage. -#define __THREAD __thread - -// Align the variable or type to at least `x` bytes. `x` must be a power of two. -#define __ALIGNED(x) __attribute__((aligned(x))) - -// Declare the given function will never return. (such as `exit`, `abort`, etc). -#define __NO_RETURN __attribute__((__noreturn__)) - -// Warn if the result of this function is ignored by the caller. -#define __WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) - -// Declare that the given stack variable may be left uninitialized if it does -// not have a specified initial value. -#if defined(__clang__) -#define __UNINITIALIZED __attribute__((uninitialized)) -#else -#define __UNINITIALIZED -#endif - -// Warn if a constructed objected is not used by the caller. -// -// Generates a warning on code like this: -// -// { -// AutoLock(&mutex); // error: the AutoLock goes out of scope immediately. -// locked_variable = 42; -// } -// -// C++17 defines [[nodiscard]] to do this, but some older but supported -// versions of GCC support [[nodiscard]] on functions but not constructors. -// Having a separate __WARN_UNUSED_CONSTRUCTOR allows us to hide the attribute -// only on constructors on old versions of GCC. -#if defined(__cplusplus) -#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 10)) -#define __WARN_UNUSED_CONSTRUCTOR [[nodiscard]] -#else -#define __WARN_UNUSED_CONSTRUCTOR -#endif -#endif - -// Mark a function or variable as deprecated, warning about any callers. -#if !defined(__DEPRECATE) -#define __DEPRECATE __attribute__((__deprecated__)) -#endif - -// Mark a function as having no visible side-effects: It may read memory, but -// will not modify it. -// -// Multiple calls to the function may be optimized away by the compiler. -#define __PURE __attribute__((__pure__)) - -// Mark a function has having an output determined solely on its input -// parameters (but not memory). -// -// Multiple calls to the function may be optimized away by the compiler, even -// if memory is modified between calls. -#define __CONST __attribute__((__const__)) - -// The given function is malloc-like, returning a pointer to new, unused -// memory. -// -// The compiler can assume that the returned pointer does not alias any other -// pointer, which may help the compiler optimize the program. -#define __MALLOC __attribute__((__malloc__)) - -// The given function allocates memory of size argument |x| or |x| * |y| and returns -// a pointer to that memory. Argument indexes are one-based. The compiler can use this -// information to support compile-time __builtin_object_size checks. -#if defined(__clang__) -#define __ALLOC_SIZE(x, ...) __attribute__((__alloc_size__(x, ##__VA_ARGS__))) -#else -// TODO(fxrev.dev/571541): GCC warns incorrectly on constructs that could result in -// large allocations for type reasons but cannot for other (checked) reasons. Disable -// the attribute there. -#define __ALLOC_SIZE(x, ...) -#endif - -// Indicate that the given function takes a printf/scanf-style format string. -// -// "__fmt" is the argument number of the format string, indexed from 1. -// "__varargs" is the argument number of the variable args "..." argument -// counting from 1. -// -// If applied to a class method, the implicit "this" parameter counts as the -// first argument. -#define __PRINTFLIKE(__fmt, __varargs) __attribute__((__format__(__printf__, __fmt, __varargs))) -#define __SCANFLIKE(__fmt, __varargs) __attribute__((__format__(__scanf__, __fmt, __varargs))) - -// Indicate that the `n`th argument to a function is non-null. -// -// The compiler will emit warnings if it can prove an argument is null, and -// may optimise assuming that the values are non-null. -#define __NONNULL(n) __attribute__((__nonnull__ n)) - -// The given function is a "leaf", and won't call further functions. -// -// Leaf functions must only return directly, and not call back into the -// current compilation unit (either via direct calls, or function pointers). -// -// May help the compiler optimize calls to the function in some cases. -#define __LEAF_FN __attribute__((__leaf__)) - -// Mark the given function or variable as `constexpr`. -// -// Used in code included by both C and C++. Code that is pure C++ should use -// `constexpr` directly. -#ifdef __cplusplus -#define __CONSTEXPR constexpr -#else -#define __CONSTEXPR -#endif - -// Optimize the given function using custom flags. -// -// For example, -// -// __OPTIMIZE("O3") int myfunction() { ... } -// -// will cause GCC to optimize the function at the O3 level, independent -// of what the compiler optimization flags are. -#if !defined(__clang__) -#define __OPTIMIZE(x) __attribute__((__optimize__(x))) -#else -#define __OPTIMIZE(x) -#endif - -// Indicate the given function should not use LLVM's stack hardening features, -// but instead put all local variables on the standard stack. -// -// c.f. https://clang.llvm.org/docs/SafeStack.html -#if defined(__clang__) -#define __NO_SAFESTACK __attribute__((__no_sanitize__("safe-stack", "shadow-call-stack"))) -#else -#define __NO_SAFESTACK -#endif - -// The given C++ class or struct need not have a unique address when part of -// a larger struct or class, but can be safely collapsed into a zero-byte -// object by the compiler. -#if __has_cpp_attribute(no_unique_address) -#define __NO_UNIQUE_ADDRESS [[no_unique_address]] -#elif __has_cpp_attribute(msvc::no_unique_address) -// msvc targets, as used by efi, have a different attribute name, even when -// targeting C++20. -#define __NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] -#else -#define __NO_UNIQUE_ADDRESS -#endif - -// Indicate that the given function should be treated by the Clang static -// analyzer as if it doesn't return. -// -// A workaround to help static analyzer identify assertion failures -#if defined(__clang__) -#define __ANALYZER_CREATE_SINK __attribute__((analyzer_noreturn)) -#else -#define __ANALYZER_CREATE_SINK -#endif - -// Mark the given function as externally visible, and shouldn't be optimized -// away by link-time optimizations or whole-program optimizations. -#if !defined(__clang__) -#define __EXTERNALLY_VISIBLE __attribute__((__externally_visible__)) -#else -#define __EXTERNALLY_VISIBLE -#endif - -// Declare that this function declaration should be emitted as an alias for -// another function. -#define __ALIAS(x) __attribute__((__alias__(x))) - -// Place the given global into a particular linker section. -#define __SECTION(x) __attribute__((__section__(x))) - -// The given function or global should be given a weak symbol, or a weak -// alias to another symbol. -#define __WEAK __attribute__((__weak__)) -#define __WEAK_ALIAS(x) __attribute__((__weak__, __alias__(x))) - -// The given static variable should still be emitted by the compiler, even if it -// appears unused to the compiler. -// -// Rarely needed. Not to be confused with "__UNUSED", which avoids the -// compiler warning if a variable appears unused. -#define __ALWAYS_EMIT __attribute__((__used__)) - -// Declare this object's ELF symbol visibility. -#define __EXPORT __attribute__((__visibility__("default"))) -#define __LOCAL __attribute__((__visibility__("hidden"))) - -// -// Builtin functions. -// - -// Provide a hint to the compiler that the given expression is likely/unlikely -// to be true. -// -// if (unlikely(status != ZX_OK)) { -// error(...); -// } -// -#ifndef likely -#define likely(x) __builtin_expect(!!(x), 1) -#endif - -#ifndef unlikely -#define unlikely(x) __builtin_expect(!!(x), 0) -#endif - -// Return the program counter of the calling function. -#define __GET_CALLER(x) __builtin_return_address(0) - -// Return the address of the current stack frame. -#define __GET_FRAME(x) __builtin_frame_address(0) - -// Return true if the given expression is a known compile-time constant. -#define __ISCONSTANT(x) __builtin_constant_p(x) - -// Assume this branch of code cannot be reached. -#define __UNREACHABLE __builtin_unreachable() - -// Get the offset of `field` from the beginning of the struct or class `type`. -#define __offsetof(type, field) __builtin_offsetof(type, field) - -// Perform an arithmetic operation, returning "true" if the operation overflowed. -// -// Equivalent to: { *result = a + b; return _overflow_occurred; } -#define add_overflow(a, b, result) __builtin_add_overflow(a, b, result) -#define sub_overflow(a, b, result) __builtin_sub_overflow(a, b, result) -#define mul_overflow(a, b, result) __builtin_mul_overflow(a, b, result) - -// Indicate the given case of a switch statement is intended to fall through -// to the next case, and avoid generating a compiler warning. -// -// switch (n) { -// case 0: -// case 1: -// handle_zero_and_one_case(); -// __FALLTHROUGH; -// default: -// handle_all_cases(); -// break; -// } -// -#if defined(__cplusplus) -#define __FALLTHROUGH [[fallthrough]] -#elif defined(__cplusplus) && defined(__clang__) -#define __FALLTHROUGH [[clang::fallthrough]] -// The GNU style attribute is supported by Clang for C code, but __GNUC__ for -// clang right now is 4. -#elif __GNUC__ >= 7 || (!defined(__cplusplus) && defined(__clang__)) -#define __FALLTHROUGH __attribute__((__fallthrough__)) -#else -#define __FALLTHROUGH \ - do { \ - } while (0) -#endif - -// Locking annotations. -// -// The following annotations allow compile-time checking that annotated data -// is only accessed while holding the correct locks. -// -// The annotations are only supported by Clang, and frequently used with C++ -// standard library types in userspace, so only enable in Clang when we know -// that the C++ standard library types are annotated or if we're in kernel -// code. -#if defined(__clang__) && (defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) || defined(_KERNEL)) -#define __THREAD_ANNOTATION(x) __attribute__((x)) -#else -#define __THREAD_ANNOTATION(x) -#endif -#define __TA_CAPABILITY(x) __THREAD_ANNOTATION(__capability__(x)) -#define __TA_GUARDED(x) __THREAD_ANNOTATION(__guarded_by__(x)) -#define __TA_ACQUIRE(...) __THREAD_ANNOTATION(__acquire_capability__(__VA_ARGS__)) -#define __TA_ACQUIRE_SHARED(...) __THREAD_ANNOTATION(__acquire_shared_capability__(__VA_ARGS__)) -#define __TA_TRY_ACQUIRE(...) __THREAD_ANNOTATION(__try_acquire_capability__(__VA_ARGS__)) -#define __TA_TRY_ACQUIRE_SHARED(...) \ - __THREAD_ANNOTATION(__try_acquire_shared_capability__(__VA_ARGS__)) -// Neither ACQUIRED_BEFORE nor ACQUIRED_AFTER are implemented in clang. Users of these macros must -// not rely upon them to catch lock ordering bugs, and must treat them as documentation only. -// See: -// https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#acquired-before-and-acquired-after-are-currently-unimplemented -#define __TA_ACQUIRED_BEFORE(...) __THREAD_ANNOTATION(__acquired_before__(__VA_ARGS__)) -#define __TA_ACQUIRED_AFTER(...) __THREAD_ANNOTATION(__acquired_after__(__VA_ARGS__)) -#define __TA_RELEASE(...) __THREAD_ANNOTATION(__release_capability__(__VA_ARGS__)) -#define __TA_RELEASE_SHARED(...) __THREAD_ANNOTATION(__release_shared_capability__(__VA_ARGS__)) -#define __TA_REQUIRES(...) __THREAD_ANNOTATION(__requires_capability__(__VA_ARGS__)) -#define __TA_REQUIRES_SHARED(...) __THREAD_ANNOTATION(__requires_shared_capability__(__VA_ARGS__)) -#define __TA_EXCLUDES(...) __THREAD_ANNOTATION(__locks_excluded__(__VA_ARGS__)) -#define __TA_ASSERT(...) __THREAD_ANNOTATION(__assert_capability__(__VA_ARGS__)) -#define __TA_ASSERT_SHARED(...) __THREAD_ANNOTATION(__assert_shared_capability__(__VA_ARGS__)) -#define __TA_RETURN_CAPABILITY(x) __THREAD_ANNOTATION(__lock_returned__(x)) -#define __TA_SCOPED_CAPABILITY __THREAD_ANNOTATION(__scoped_lockable__) -#define __TA_NO_THREAD_SAFETY_ANALYSIS __THREAD_ANNOTATION(__no_thread_safety_analysis__) - -// Experimental lifetime analysis annotations. -#ifndef __OWNER -#ifdef __clang__ -#define __OWNER(x) [[gsl::Owner(x)]] -#define __POINTER(x) [[gsl::Pointer(x)]] -#else -#define __OWNER(x) -#define __POINTER(x) -#endif -#endif - -#if defined(__cpp_constinit) && __cpp_constinit >= 201907L -#define __CONSTINIT constinit -#elif defined(__clang__) -#define __CONSTINIT [[clang::require_constant_initialization]] -#elif defined(__GNUC__) && __GNUC__ >= 13 -#define __CONSTINIT __constinit -#else -#define __CONSTINIT -#endif - -#endif // !defined(__ASSEMBLER__) - -#endif // ZIRCON_COMPILER_H_ |
