diff --git a/docs/agents/code-style.md b/docs/agents/code-style.md index c884380..94d4345 100644 --- a/docs/agents/code-style.md +++ b/docs/agents/code-style.md @@ -45,7 +45,10 @@ - 如果代码依赖硬件手册、启动协议、调用顺序或特殊寄存器状态,应写明约束。 - 如果一个实现是临时简化,应写清楚后续替换边界,而不是写成永久接口。 - 公共头文件 `include/tianole/*.h` 中的函数声明必须使用 Linux kernel-doc 风格块注释。 +- 公共结构体、枚举、typedef 和长期宏常量也必须使用 kernel-doc 风格块注释。 - 公共函数注释至少说明函数职责、关键参数、返回值或副作用;不要只复述函数名。 +- 公共类型注释要说明字段含义、所有权、生命周期或并发约束。 +- 公共宏注释要说明它代表的协议常量、标志位或长期 ABI 含义。 - 公共函数声明和前一个声明/注释块之间必须留一个空行,避免 API 挤在一起。 - 私有 `static` 小函数不要求每个都写函数头注释;只有逻辑、数据流、锁语义或硬件约束不明显时才写。 - 多行注释要控制行宽,优先写职责、数据流和调用约束,而不是描述每一行代码。 diff --git a/include/tianole/boot_info.h b/include/tianole/boot_info.h index 1a808f9..a8158b4 100644 --- a/include/tianole/boot_info.h +++ b/include/tianole/boot_info.h @@ -3,8 +3,26 @@ #include +/** + * BOOT_MEMORY_TYPE_CONVENTIONAL - Firmware memory type for usable RAM. + * + * Mirrors the UEFI conventional memory type used by the bootloader handoff. + * The kernel converts this into its own long-term memory model during MM init. + */ #define BOOT_MEMORY_TYPE_CONVENTIONAL 7u +/** + * typedef boot_memory_descriptor_t - Boot memory map descriptor. + * @type: Firmware memory type. + * @pad: Reserved padding used to keep the handoff layout stable. + * @physical_start: Physical base address of this region. + * @virtual_start: Firmware virtual address field, currently preserved only. + * @number_of_pages: Region size in 4 KiB pages. + * @attribute: Firmware attributes for the region. + * + * Describes one memory map entry copied from firmware-owned data into the + * Tianole boot handoff format. + */ typedef struct { uint32_t type; uint32_t pad; @@ -14,10 +32,19 @@ typedef struct { uint64_t attribute; } boot_memory_descriptor_t; -/* - * Boot-time handoff data owned by Tianole rather than by a specific - * firmware or architecture API. Fields can grow over time while the - * kernel entry stays stable. +/** + * typedef boot_info_t - Bootloader-to-kernel handoff data. + * @version: Handoff structure version. + * @boot_flags: Flags describing the firmware handoff state. + * @memory_map: Physical address of boot_memory_descriptor_t entries. + * @memory_map_size: Total memory map size in bytes. + * @memory_map_key: Firmware key captured before ExitBootServices(). + * @memory_descriptor_size: Size of each memory descriptor entry. + * @memory_descriptor_version: Firmware descriptor version. + * @reserved0: Reserved field for alignment and future expansion. + * + * Boot-time handoff data owned by Tianole rather than by a specific firmware + * or architecture API. Fields can grow while the kernel entry stays stable. */ typedef struct { uint32_t version; @@ -30,7 +57,14 @@ typedef struct { uint32_t reserved0; } boot_info_t; +/** + * BOOT_INFO_VERSION - Current boot_info_t layout version. + */ #define BOOT_INFO_VERSION 1u + +/** + * BOOT_FLAG_SERVICES_ACTIVE - Firmware boot services were active at handoff. + */ #define BOOT_FLAG_SERVICES_ACTIVE (1u << 0) #endif diff --git a/include/tianole/elf.h b/include/tianole/elf.h index f105986..05aca8b 100644 --- a/include/tianole/elf.h +++ b/include/tianole/elf.h @@ -3,16 +3,61 @@ #include +/** + * ELF_MAGIC - ELF file magic value in little-endian word form. + */ #define ELF_MAGIC 0x464c457fu + +/** + * ELFCLASS64 - ELF identification value for 64-bit objects. + */ #define ELFCLASS64 2 + +/** + * ELFDATA2LSB - ELF identification value for little-endian objects. + */ #define ELFDATA2LSB 1 + +/** + * EV_CURRENT - Current ELF object format version. + */ #define EV_CURRENT 1 +/** + * ET_EXEC - ELF object type for executable files. + */ #define ET_EXEC 2 + +/** + * EM_X86_64 - ELF machine type for x86_64. + */ #define EM_X86_64 62 +/** + * PT_LOAD - ELF program header type for loadable segments. + */ #define PT_LOAD 1 +/** + * typedef elf64_ehdr_t - ELF64 file header. + * @ident: ELF identification bytes. + * @type: Object file type. + * @machine: Target machine architecture. + * @version: ELF object version. + * @entry: Entry point virtual address. + * @phoff: Program header table file offset. + * @shoff: Section header table file offset. + * @flags: Processor-specific flags. + * @ehsize: ELF header size. + * @phentsize: Size of one program header entry. + * @phnum: Number of program header entries. + * @shentsize: Size of one section header entry. + * @shnum: Number of section header entries. + * @shstrndx: Section name string table index. + * + * Used by the bootloader and future ELF loader to validate and locate image + * segments without depending on host libc headers. + */ typedef struct { unsigned char ident[16]; uint16_t type; @@ -30,6 +75,20 @@ typedef struct { uint16_t shstrndx; } elf64_ehdr_t; +/** + * typedef elf64_phdr_t - ELF64 program header. + * @type: Segment type. + * @flags: Segment permissions. + * @offset: Segment file offset. + * @vaddr: Segment virtual address. + * @paddr: Segment physical address, if meaningful for the image. + * @filesz: Number of bytes present in the file. + * @memsz: Number of bytes required in memory. + * @align: Segment alignment requirement. + * + * Describes one loadable or metadata segment consumed by boot and future + * user-mode ELF loading paths. + */ typedef struct { uint32_t type; uint32_t flags; diff --git a/include/tianole/mm.h b/include/tianole/mm.h index ec11a48..5094db0 100644 --- a/include/tianole/mm.h +++ b/include/tianole/mm.h @@ -6,13 +6,38 @@ #include +/** + * PAGE_SIZE - Base page size used by the current memory manager. + */ #define PAGE_SIZE 4096u +/** + * typedef phys_addr_t - Physical address value. + * + * Represents addresses in physical memory, not directly dereferenceable by C. + */ typedef uint64_t phys_addr_t; + +/** + * typedef virt_addr_t - Virtual address value. + * + * Represents addresses in the active virtual address space. + */ typedef uint64_t virt_addr_t; +/** + * PAGE_PRESENT - Mapping flag that marks a page table entry present. + */ #define PAGE_PRESENT (1ull << 0) + +/** + * PAGE_WRITABLE - Mapping flag that allows writes through a page mapping. + */ #define PAGE_WRITABLE (1ull << 1) + +/** + * PAGE_NO_EXECUTE - Mapping flag that blocks instruction fetches. + */ #define PAGE_NO_EXECUTE (1ull << 63) /** diff --git a/include/tianole/sched.h b/include/tianole/sched.h index 4359acc..ae05f94 100644 --- a/include/tianole/sched.h +++ b/include/tianole/sched.h @@ -6,9 +6,31 @@ #include +/** + * typedef kernel_thread_entry_t - Kernel thread entry function. + * @arg: Opaque argument supplied at thread creation. + * + * The function runs in kernel thread context. Returning from it is equivalent + * to calling kernel_thread_exit(). + */ typedef void (*kernel_thread_entry_t)(void *arg); + +/** + * typedef wait_condition_t - Wait queue condition predicate. + * @arg: Opaque predicate argument supplied by the caller. + * + * Return: Non-zero when the condition is satisfied, zero to keep waiting. + */ typedef int (*wait_condition_t)(void *arg); +/** + * enum thread_state - Scheduler-visible thread lifecycle state. + * @THREAD_READY: Thread is runnable and may be selected by the scheduler. + * @THREAD_RUNNING: Thread is currently executing on the CPU. + * @THREAD_SLEEPING: Thread is blocked until a timer deadline. + * @THREAD_WAITING: Thread is blocked on a wait queue. + * @THREAD_DEAD: Thread has exited and is waiting for safe reclamation. + */ enum thread_state { THREAD_READY, THREAD_RUNNING, @@ -17,12 +39,39 @@ enum thread_state { THREAD_DEAD, }; +/** + * struct wait_queue - Queue of threads blocked on an event or condition. + * @lock: Interrupt-safe lock protecting queue links and wakeup state. + * @head: Oldest waiting thread. + * @tail: Newest waiting thread. + * + * The queue owns only wait links. The condition being waited on may be owned + * by another subsystem and must have a documented synchronization rule. + */ struct wait_queue { struct spinlock lock; struct thread *head; struct thread *tail; }; +/** + * struct thread - Kernel scheduler thread object. + * @id: Scheduler-assigned thread identifier. + * @state: Current scheduler state. + * @stack_pointer: Saved context stack pointer for context switching. + * @entry: Thread entry function. + * @arg: Entry function argument. + * @stack_base: Allocated kernel stack base. + * @stack_top: Aligned initial stack top. + * @stack_size: Kernel stack size in bytes. + * @wake_tick: Timer tick deadline for sleeping threads. + * @next: Run queue link owned by the scheduler. + * @wait_next: Wait queue link owned by wait queue code. + * @name: Diagnostic thread name. + * + * This structure is public only as an early-stage compromise. Long term, most + * fields should move behind scheduler-private helpers or an opaque handle. + */ struct thread { uint64_t id; enum thread_state state; diff --git a/include/tianole/spinlock.h b/include/tianole/spinlock.h index ffceb0a..eef2f44 100644 --- a/include/tianole/spinlock.h +++ b/include/tianole/spinlock.h @@ -3,10 +3,20 @@ #include +/** + * struct spinlock - Early interrupt-safe lock. + * @locked: Non-zero while the lock is held. + * + * Current implementation is single-CPU and panics on contention. The API is + * shaped so it can later grow toward a real SMP spinlock. + */ struct spinlock { int locked; }; +/** + * SPINLOCK_INITIALIZER - Static initializer for struct spinlock. + */ #define SPINLOCK_INITIALIZER \ { \ 0 \ diff --git a/scripts/tools/check_structure.py b/scripts/tools/check_structure.py index 0ca6d0e..8fa7007 100644 --- a/scripts/tools/check_structure.py +++ b/scripts/tools/check_structure.py @@ -152,6 +152,71 @@ def collect_function_declarations(lines: list[str]) -> list[tuple[int, int, str] return decls +def is_public_type_start(line: str) -> bool: + stripped = line.strip() + + if stripped.startswith(("struct ", "enum ", "union ")): + return stripped.endswith("{") or "{" in stripped + + if not stripped.startswith("typedef "): + return False + + return "(" not in stripped + + +def collect_public_type_declarations(lines: list[str]) -> list[tuple[int, int, str]]: + decls = [] + index = 0 + + while index < len(lines): + if not is_public_type_start(lines[index]): + index += 1 + continue + + start = index + text = lines[index].strip() + while ";" not in lines[index]: + index += 1 + if index >= len(lines): + break + text += " " + lines[index].strip() + + if index < len(lines): + decls.append((start, index, text)) + + index += 1 + + return decls + + +def is_documented_public_define(lines: list[str], index: int, guard: str | None) -> bool: + stripped = lines[index].strip() + + if not stripped.startswith("#define "): + return False + + parts = stripped.split() + if len(parts) < 2: + return False + + name = parts[1].split("(", 1)[0] + if name == guard: + return False + + return True + + +def header_guard_name(lines: list[str]) -> str | None: + for line in lines: + stripped = line.strip() + if stripped.startswith("#define "): + parts = stripped.split() + if len(parts) >= 2: + return parts[1] + + return None + + def has_kernel_doc_before(lines: list[str], start: int) -> bool: index = start - 1 @@ -187,26 +252,56 @@ def has_blank_line_before_doc(lines: list[str], start: int) -> bool: return lines[index - 1].strip() == "" -def check_public_header_function_docs(root: Path, files: list[Path]) -> list[str]: +def symbol_name_from_type_declaration(text: str) -> str: + if text.startswith("typedef "): + return text.rsplit("}", 1)[-1].strip().rstrip(";").split()[-1] + + parts = text.split() + if len(parts) >= 2: + return parts[1] + + return "" + + +def check_kernel_doc_block( + errors: list[str], path: Path, lines: list[str], start: int, kind: str, name: str +) -> None: + line_no = start + 1 + + if not has_kernel_doc_before(lines, start): + errors.append( + f"{path}:{line_no}: public {kind} '{name}' needs " + "a kernel-doc comment immediately before it" + ) + return + + if not has_blank_line_before_doc(lines, start): + errors.append( + f"{path}:{line_no}: public {kind} '{name}' " + "comment block must be separated by a blank line" + ) + + +def check_public_header_docs(root: Path, files: list[Path]) -> list[str]: errors = [] for path in files: lines = read_text(root, path).splitlines() for start, _end, text in collect_function_declarations(lines): - line_no = start + 1 name = text.split("(", 1)[0].split()[-1].lstrip("*") - if not has_kernel_doc_before(lines, start): - errors.append( - f"{path}:{line_no}: public function '{name}' needs " - "a kernel-doc comment immediately before it" - ) + check_kernel_doc_block(errors, path, lines, start, "function", name) + + for start, _end, text in collect_public_type_declarations(lines): + name = symbol_name_from_type_declaration(text) + check_kernel_doc_block(errors, path, lines, start, "type", name) + + guard = header_guard_name(lines) + for index, line in enumerate(lines): + if not is_documented_public_define(lines, index, guard): continue - if not has_blank_line_before_doc(lines, start): - errors.append( - f"{path}:{line_no}: public function '{name}' " - "comment block must be separated by a blank line" - ) + name = line.strip().split()[1].split("(", 1)[0] + check_kernel_doc_block(errors, path, lines, index, "macro", name) return errors @@ -313,7 +408,7 @@ def main() -> int: errors = [] errors.extend(check_no_relative_parent_includes(root, source_files(files))) - errors.extend(check_public_header_function_docs(root, public_headers(files))) + errors.extend(check_public_header_docs(root, public_headers(files))) errors.extend(check_selftests_are_centralized(c_files(files))) errors.extend(check_makefile_source_lists(root, files, all_mode))