Skip to content

Latest commit

 

History

History
1750 lines (1078 loc) · 26.8 KB

File metadata and controls

1750 lines (1078 loc) · 26.8 KB

============================

Serix Kernel API Reference

Overview

This document provides the internal API reference for Serix kernel subsystems. It specifies the contracts between kernel modules including memory management, task scheduling, interrupt handling, hardware abstraction, and system calls.

The Serix kernel is a microkernel-style operating system written in Rust, featuring capability-based security and a workspace-based cargo architecture.

Design Principles

Type Safety Leverage Rust's type system for compile-time safety guarantees

Minimal Unsafe Isolate unsafe operations to specific hardware abstraction modules

Zero-Cost Abstractions Ensure abstractions compile to optimal machine code with no runtime overhead

Clear Ownership Explicit ownership and borrowing semantics throughout the codebase

Error Handling Use Result and Option types where appropriate; panic on unrecoverable errors

Subsystem Architecture

The kernel consists of independent workspace crates


kernel/         Entry point, syscalls, global initialization
memory/         Page tables, heap allocator, frame allocation
hal/            Hardware abstraction (serial, CPU topology)
apic/           APIC interrupt controller (Local APIC, I/O APIC, timer)
idt/            Interrupt Descriptor Table management
graphics/       Framebuffer console and drawing primitives
task/           Async executor, scheduler, task control blocks
capability/     Capability-based security system
drivers/        Device drivers (VirtIO, PCI, console)
vfs/            Virtual filesystem (ramdisk, INode abstraction)
fs/             FAT32 filesystem driver
ipc/            Inter-process communication
loader/         ELF userspace binary loader
ulib/           Userspace library (syscall wrappers)

Current Status (v0.0.6)

System Calls 10 syscalls implemented: serix_write, serix_read, serix_open, serix_close, serix_seek, serix_exit, serix_yield, serix_send, serix_recv, serix_recv_block

VFS Path resolution via lookup_path(), global VFS root, FAT32 filesystem mounted from VirtIO block device

Task Scheduler Preemptive round-robin scheduling with LAPIC timer at ~625 Hz

Filesystem FAT32 driver with BPB parsing, cluster chains, directory entries (8.3+LFN), file read/write

File Descriptors Global FD table keyed by (task_id, fd); open/close/seek operations

Userspace Init binary loads and executes from ramdisk

Memory Management Working page tables, heap allocator, frame allocation

Interrupts IDT loaded, APIC enabled, timer and keyboard interrupts functional

Memory Management

The memory subsystem provides page table management, heap allocation, and physical frame allocation. All physical RAM is mapped at virtual offset 0xFFFF_8000_0000_0000 (HHDM - Higher Half Direct Map).

Page Table Management

init_offset_page_table()


Initialize offset page table mapper with active page table

pub unsafe fn init_offset_page_table(offset: VirtAddr) -> OffsetPageTable<'static>

Parameters:
    offset
        Virtual address offset for physical memory mapping, typically
        0xFFFF_8000_0000_0000 from Limine HHDM response

Returns:
    OffsetPageTable<'static> mapper instance

Safety:
    - Caller must ensure offset correctly maps physical memory
    - Must be called only once during boot
    - Requires valid CR3 register value

Example usage

let phys_mem_offset = VirtAddr::new(0xFFFF_8000_0000_0000); let mut mapper = unsafe { memory::init_offset_page_table(phys_mem_offset) };

// Translate virtual to physical use x86_64::structures::paging::Page; let page = Page::containing_address(VirtAddr::new(0x4444_4444_0000)); mapper.translate_page(page);

Notes:
    Returns reference to active level-4 page table. Enables direct physical
    memory access via offset mapping. All physical addresses converted as:
    virt = 0xFFFF_8000_0000_0000 + phys


BootFrameAllocator

Physical frame allocator using bootloader memory map


pub struct BootFrameAllocator {
}

impl BootFrameAllocator {
}

Purpose: Allocates physical memory frames (4KiB pages) from usable memory regions identified by the bootloader

Trait Implementation


unsafe impl FrameAllocator<Size4KiB> for BootFrameAllocator {
}

Algorithm: Simple bump allocator, no deallocation support

Example usage


let mmap_response = MMAP_REQ.get_response().expect("No memory map");
let entries = mmap_response.entries();
let mut frame_allocator = BootFrameAllocator::new(entries);

// Allocate a frame
if let Some(frame) = frame_allocator.allocate_frame() {
}

StaticBootFrameAllocator


Pre-heap frame allocator using static array storage

pub struct StaticBootFrameAllocator { }

impl StaticBootFrameAllocator { }


Purpose:
    Frame allocator that works before heap initialization, stores frames
    in static array

Storage

pub static mut BOOT_FRAMES: [Option; MAX_BOOT_FRAMES] = pub const MAX_BOOT_FRAMES: usize = 65536;


Example usage

// Preallocate frames to static array let mut frame_count = 0; for region in usable_regions { }

// Create allocator let mut frame_alloc = StaticBootFrameAllocator::new(frame_count); memory::init_heap(&mut mapper, &mut frame_alloc);



## Heap Management

init_heap()

Map and initialize kernel heap for dynamic memory allocation


pub fn init_heap(
)

Parameters: mapper Page table mapper for creating virtual mappings

frame_allocator
    Allocator for obtaining physical frames

Side Effects: - Maps heap region (0xFFFF_8000_4444_0000 to 0xFFFF_8000_4454_0000) - Initializes global heap allocator - Enables Rust alloc crate functionality (Vec, Box, String)

Panics: If frame allocation fails or mapping fails

Constants


pub const HEAP_START: usize = 0xFFFF_8000_4444_0000;
pub const HEAP_SIZE: usize = 1024 * 1024;  // 1 MiB

Example usage


// After initializing mapper and frame allocator
memory::init_heap(&mut mapper, &mut frame_alloc);

// Now heap allocations work
extern crate alloc;
use alloc::vec::Vec;
let mut v = Vec::new();
v.push(1);
v.push(2);

.. note


Must be called before any heap allocations (Vec, Box, String).
Heap initialization is a one-time operation during boot.

Address Translation

Helper functions for physical-virtual address conversion


// Convert physical to virtual (kernel space)
pub fn phys_to_virt(phys: PhysAddr) -> VirtAddr {
}

// Convert virtual to physical (if in physical mapping region)
pub fn virt_to_phys(virt: VirtAddr) -> Option<PhysAddr> {
}

Task Management

The task subsystem provides async-based task execution, scheduling primitives, and context switching. Current implementation is minimal (v0.0.6) with no preemptive scheduling.

Task Identification

TaskId


Unique identifier for tasks

pub struct TaskId(pub u64);

impl TaskId { }

Thread Safety:
    Uses atomic counter, safe to call from multiple contexts

Example usage

let task_id = TaskId::new(); serial_println!("Created task ID: {}", task_id.as_u64());


## Task State

Task lifecycle states

pub enum TaskState { }


## Scheduling Classes

Scheduling policies and priorities

pub enum SchedClass { }

impl Default for SchedClass { }


## CPU Context

Complete CPU state for context switching

[repr(C)] [derive(Debug, Clone, Copy)] pub struct CPUContext { }


## Task Control Block

TaskCB

Represents a schedulable task


pub struct TaskCB {
}

impl TaskCB {

}

new() ^^^^^

Create new task control block


pub fn new(
) -> Self

Parameters: name Human-readable task name for debugging

entry_point
    Function to execute when task runs, must never return

stack
    Top of kernel stack for this task

sched_class
    Scheduling policy and priority

Returns: Initialized TaskCB in Ready state

Example usage


extern "C" fn my_task() -> ! {
}

let stack = VirtAddr::new(0xFFFF_8000_0001_0000);
let task = TaskCB::new(
);

Task Builder

Builder pattern for task creation


pub struct TaskBuilder {
}

impl TaskBuilder {
}

Example usage


let task = TaskBuilder::new("background_worker")

Scheduler::global().lock().add_task(task);

Scheduler

Global task scheduler


pub struct Scheduler {
}

impl Scheduler {
}

init_global()


Initialize global scheduler instance

pub fn init_global()


Must be called once during kernel initialization before any tasks are created.

Example

Scheduler::init_global();


global()

Access global scheduler


pub fn global() -> &'static spin::Mutex<Scheduler>

Returns: Reference to global scheduler protected by spinlock

Example


let mut sched = Scheduler::global().lock();
sched.add_task(task);
serial_println!("Task count: {}", sched.task_count());

add_task()


Add task to scheduler run queue

pub fn add_task(&mut self, task: TaskCB)



## Context Switching

context_switch()

Low-level context switch between tasks


[naked]
pub unsafe extern "C" fn context_switch(
)

Parameters: old Pointer to save current CPU context

new
    Pointer to load new CPU context

Safety: - Must be called with valid context pointers - Pointers must remain valid for entire operation - Should only be called by scheduler

Example (internal scheduler use)


let old_ctx = &mut tasks[current_idx].context as *mut CPUContext;
let new_ctx = &tasks[next_idx].context as*const CPUContext;
unsafe {
}

task_yield()


Voluntarily yield CPU to another task

pub fn task_yield()

Example

extern "C" fn cooperative_task() -> ! { }


## System Calls


The syscall subsystem provides the interface between userspace programs and
the kernel. Currently implements 10 syscalls.


## Syscall Numbers

Syscall vector assignments

const SYS_READ: u64 = 0; const SYS_WRITE: u64 = 1; const SYS_OPEN: u64 = 2; const SYS_CLOSE: u64 = 3; const SYS_SEEK: u64 = 8; const SYS_SEND: u64 = 20; const SYS_RECV: u64 = 21; const SYS_RECV_BLOCK: u64 = 22; const SYS_YIELD: u64 = 24; const SYS_EXIT: u64 = 60;


## Calling Convention

Syscalls use the SYSCALL instruction (x86_64 fast syscall mechanism)

rax Syscall number rdi Argument 1 rsi Argument 2 rdx Argument 3 r10 Argument 4 (rcx is clobbered by SYSCALL) r8 Argument 5 r9 Argument 6

Return value in rax


## serix_write()

Write bytes to file descriptor

pub fn serix_write(fd: u64, buf: *const u8, count: u64) -> u64

Parameters:
    fd
        File descriptor (1 = stdout, 2 = stderr)

    buf
        Pointer to data buffer

    count
        Number of bytes to write

Returns:
    Number of bytes written, or error code

Example (userspace)

use ulib::serix_write;

let msg = b"Hello from userspace\n"; let written = serix_write(1, msg.as_ptr(), msg.len() as u64);

Kernel Handler

// kernel/src/syscall.rs fn sys_write(fd: u64, buf: u64, count: u64) -> u64 { }


## serix_read()

Read bytes from file descriptor

pub fn serix_read(fd: u64, buf: *mut u8, count: u64) -> u64

Parameters:
    fd
        File descriptor (0 = stdin)

    buf
        Pointer to buffer for data

    count
        Maximum bytes to read

Returns:
    Number of bytes read, or error code

Example (userspace)

use ulib::serix_read;

let mut buf = [0u8; 128]; let read_count = serix_read(0, buf.as_mut_ptr(), 128);


## serix_exit()

Terminate current task

pub fn serix_exit(code: u64) -> !

Parameters:
    code
        Exit status code

Never returns (task is terminated).

Example (userspace)

use ulib::serix_exit;

serix_exit(0); // Success


## serix_yield()

Yield CPU to scheduler

pub fn serix_yield()

Voluntarily gives up remaining timeslice to allow other tasks to run.

Example (userspace)

use ulib::serix_yield;

loop { }


## serix_open()

Open a file by path

pub fn serix_open(path: &str) -> isize

Parameters:
    path
        Absolute path (e.g. "/hello.txt")

Returns:
    File descriptor (>= 3) on success, or negative errno on error

Error Codes:
    ENOENT (-2): Path not found
    EFAULT (-14): Invalid pointer
    EINVAL (-22): Invalid UTF-8 path

Example (userspace)

use ulib::serix_open;

let fd = serix_open("/hello.txt"); if fd >= 3 { // fd is valid, use with read/write/close }


## serix_close()

Close a file descriptor

pub fn serix_close(fd: usize) -> isize

Parameters:
    fd
        File descriptor to close

Returns:
    0 on success, EBADF if fd not found

Example (userspace)

use ulib::serix_close;

serix_close(fd);


## serix_seek()

Set file read/write cursor position

pub fn serix_seek(fd: usize, offset: usize) -> isize

Parameters:
    fd
        File descriptor
    offset
        New byte offset from start of file

Returns:
    0 on success, EBADF if fd not found

Example (userspace)

use ulib::serix_seek;

serix_seek(fd, 0); // Seek back to start


## Interrupt Management



The IDT subsystem loads interrupt handlers and manages CPU exceptions.


## IDT Initialization

init_idt()

Load Interrupt Descriptor Table into CPU


pub fn init_idt()

Side Effects: - Loads IDT into IDTR register - Marks IDT as loaded globally

Must be called during kernel initialization before enabling interrupts.

Example usage


idt::init_idt();
x86_64::instructions::interrupts::enable();  // Now safe

Panics: None (will triple fault if IDT entries are invalid)

Dynamic Handler Registration

register_interrupt_handler()


Register or update interrupt handler after IDT is loaded

pub fn register_interrupt_handler( )


Parameters:
    vector
        Interrupt vector number (32-255 for hardware interrupts)

    handler
        Interrupt handler function following x86-interrupt calling convention

Safety:
    Handler must follow x86-interrupt ABI

Example usage

extern "x86-interrupt" fn custom_handler(_frame: InterruptStackFrame) { }

unsafe { }


Reloads IDT automatically if already loaded.


## Exception Handlers

Pre-registered CPU exception handlers:

Divide by Zero (Vector 0)


extern "x86-interrupt" fn divide_by_zero_handler(_stack: InterruptStackFrame)

Triggered By: Division by zero or division overflow

Action: Calls util::panic::oops("Divide by Zero exception")

Page Fault (Vector 14)



extern "x86-interrupt" fn page_fault_handler( )

Triggered By:
    Invalid memory access (not present, protection violation, reserved bits)

Information Provided:
    - Faulting address (from CR2 register)
    - Error code (present, write, user, reserved, instruction fetch flags)
    - Instruction pointer from stack frame

Action:
    Logs fault details to serial console and halts

Double Fault (Vector 8)

extern "x86-interrupt" fn double_fault_handler(
) -> !

Triggered By: Exception during exception handling (system in inconsistent state)

Action: Panics immediately, never returns

Hardware Interrupt Handlers

Keyboard (Vector 33)



extern "x86-interrupt" fn keyboard_interrupt_handler(_frame: InterruptStackFrame)

IRQ:
    IRQ1 (PS/2 keyboard controller)

Action:
    1. Read scancode from I/O port 0x60
    2. Call keyboard::handle_scancode(scancode)
    3. Send EOI to APIC


## APIC Management


The APIC subsystem manages the Advanced Programmable Interrupt Controller,
including Local APIC, I/O APIC, and LAPIC timer.


## Local APIC

enable()

Enable Local APIC and disable legacy PIC


pub unsafe fn enable()

Side Effects: - Sets APIC Global Enable bit in IA32_APIC_BASE MSR - Sets APIC Software Enable bit in SVR register - Remaps and masks all legacy PIC interrupts

Must be called before using any APIC functionality.

Example usage


unsafe {
}

send_eoi()


Signal End of Interrupt to Local APIC

pub unsafe fn send_eoi()

Must be called at end of every hardware interrupt handler (not CPU exceptions).

Example usage

extern "x86-interrupt" fn interrupt_handler(_frame: InterruptStackFrame) {

}

set_timer()

Configure Local APIC timer (low-level interface)


pub unsafe fn set_timer(vector: u8, divide: u32, initial_count: u32)

Parameters: vector Interrupt vector number (32-255)

divide
    Divider configuration value (0-11)

initial_count
    Timer period in bus cycles

Example usage


unsafe {
}

Note: Prefer using apic::timer::init_hardware() for standard timer configuration.

I/O APIC

init_ioapic()


Initialize I/O APIC with default IRQ routing

pub unsafe fn init_ioapic()

Default Mappings:
    - IRQ0 (PIT timer) → Vector 32
    - IRQ1 (keyboard) → Vector 33

Example usage

unsafe { }

map_irq()

Map hardware IRQ to interrupt vector


pub unsafe fn map_irq(irq: u8, vector: u8)

Parameters: irq Hardware IRQ number (0-23)

vector
    Interrupt vector number (32-255)

Example usage


unsafe {
}

APIC Timer

register_handler()


Register timer interrupt handler with IDT

pub unsafe fn register_handler()

Must be called before idt::init_idt().

Example usage

unsafe { } idt::init_idt();

init_hardware()

Configure and start LAPIC timer hardware


pub unsafe fn init_hardware()

Must be called after idt::init_idt() and interrupts enabled.

Configuration: - Vector: 49 (0x31) - Mode: Periodic - Divider: 16 - Frequency: ~625 Hz

Example usage


idt::init_idt();
x86_64::instructions::interrupts::enable();
unsafe {
}

ticks()


Get timer tick count since boot

pub fn ticks() -> u64

Returns:
    Number of timer interrupts since kernel started

Thread Safety:
    Safe to call (reads from static variable)

Example usage

let start = apic::timer::ticks(); do_work(); let end = apic::timer::ticks(); serial_println!("Work took {} ticks", end - start);


## Hardware Abstraction Layer



## Serial Console

init_serial()

Initialize COM1 serial port


pub fn init_serial()

Configuration: - Port: COM1 (0x3F8) - Baud rate: 38400 - Data bits: 8 - Stop bits: 1 - Parity: None

Must be called first during kernel initialization for debug output.

serial_println!()


Print line to serial console

serial_println!("format string", args...)

Macro for formatted output to serial port. Safe to call from interrupt context.

Example usage

serial_println!("Kernel booting..."); serial_println!("APIC ID: {}", apic_id);


## Utility Functions



## Panic Handling

oops()

Handle kernel oops (non-recoverable error)


pub fn oops(msg: &str) -> !

Parameters: msg Error message to display

Behavior: - Prints message with [KERNEL OOPS] prefix to serial console - Enters infinite halt loop - Never returns

Example usage


if !is_valid(ptr) {
}

Use Cases: - CPU exceptions (from exception handlers) - Hardware errors - Assertion failures - Unrecoverable kernel state corruption

halt_loop()


Enter infinite halt loop (low power)

pub fn halt_loop() -> !

Behavior:
    - Executes HLT instruction in infinite loop
    - CPU wakes on interrupt, then halts again
    - Never returns

Power Efficiency:
    Uses ~1% CPU vs busy-wait loop at 100%

Example usage

serial_println!("System halted"); halt_loop();


## Virtual Filesystem

The VFS subsystem provides filesystem abstraction with a trait-based INode
interface, global root directory, path resolution, and FAT32 backend.

## VFS Root and Path Resolution

set_root()

Set the global VFS root inode


pub fn set_root(root: Arc<dyn INode>)

Parameters: root Root directory inode (typically FatDirINode::root() or RamDir)

Must be called once during boot after filesystem mount.

lookup_path()


Resolve an absolute path to an inode

pub fn lookup_path(path: &str) -> Option<Arc>

Parameters:
    path
        Absolute path (e.g. "/hello.txt", "/subdir/file.txt", or "/")

Returns:
    Some(inode) if path resolves successfully, None otherwise

Algorithm:
    Splits path by '/' and iteratively calls INode::lookup() on each component
    starting from VFS_ROOT.

## INode Trait

pub trait INode: Send + Sync { fn read(&self, offset: usize, buf: &mut [u8]) -> usize; fn write(&self, offset: usize, buf: &[u8]) -> usize; fn metadata(&self) -> FileType; fn lookup(&self, name: &str) -> Option<Arc>; fn insert(&self, name: &str, node: Arc) -> Result<(), &'static str>; fn size(&self) -> usize; }


Implementations:
    RamFile — In-memory file with Mutex<Vec<u8>> storage
    RamDir — In-memory directory with Vec<(String, Arc<dyn INode>)> children
    FatDirINode — FAT32 directory backed by cluster chain on disk
    FatFileINode — FAT32 file backed by cluster chain on disk

## File Descriptor Table

// kernel/src/fd.rs pub fn open(task_id: u64, path: &str) -> Option pub fn close(task_id: u64, fd: u64) -> bool pub fn get(task_id: u64, fd: u64) -> Option<Arc> pub fn seek(task_id: u64, fd: u64, offset: usize) -> bool


Storage:
    Global BTreeMap<(task_id, fd), Arc<OpenFile>> protected by spin::Mutex

OpenFile:
    inode: Arc<dyn INode> — backing VFS node
    offset: Mutex<usize> — current read/write cursor

FD Allocation:
    FDs 0-2 reserved (stdin/stdout/stderr)
    User files start at fd 3 (monotonically increasing)


## Boot Sequence


## Initialization Order

Critical subsystem initialization sequence

  1. HAL (Hardware Abstraction Layer)

  2. APIC (Interrupt Controller)

  3. IDT (Interrupt Handlers)

  4. Enable Interrupts

  5. Timer Start

  6. Memory (Paging and Heap)

  7. Graphics

  8. VFS

  9. Scheduler

.. warning

Heap must be initialized before any allocations (Vec, Box, String). Interrupts must be enabled after IDT is loaded. Serial console should be initialized first for debug output.


## Data Flow Examples

Keyboard Input Flow

PS/2 Hardware → I/O Port 0x60 → I/O APIC → LAPIC
Keyboard Interrupt (Vector 33, IDT)
keyboard::handle_scancode()

Timer Tick Flow



LAPIC Timer → Timer Interrupt (Vector 49, IDT) apic::timer::timer_interrupt()

Page Fault Flow

Invalid Memory Access → CPU Exception #14
idt::page_fault_handler()

Synchronization

Thread Safety Guarantees

Single-Core Assumptions: Current Serix assumes single-core BSP only: - No SMP support - No true parallel execution - Interrupts provide only concurrency

Synchronization Primitives

Spin Mutex



use spin::Mutex;

static DATA: Mutex = Mutex::new(0);

// Usage let mut data = DATA.lock(); *data += 1; // Lock automatically released when guard drops

Once Initialization

use spin::Once;

static INIT: Once<MyStruct> = Once::new();

fn get_instance() -> &'static MyStruct {
}

Interrupt Safety

Disable interrupts for critical sections


 x86_64::instructions::interrupts::without_interrupts( || {
}); // Interrupts restored here

Common Types and Constants

Type Aliases


use x86_64::{VirtAddr, PhysAddr};
use x86_64::structures::paging::{Page, PhysFrame, Size4KiB};
use x86_64::structures::idt::InterruptStackFrame;

Memory Constants


// Physical memory mapping
const PHYS_MEM_OFFSET: u64 = 0xFFFF_8000_0000_0000;  // HHDM offset

// Kernel heap
const HEAP_START: usize = 0xFFFF_8000_4444_0000;
const HEAP_SIZE: usize = 1024 * 1024;  // 1 MiB
const MAX_BOOT_FRAMES: usize = 65536;

APIC Constants


const APIC_BASE: u64 = 0xFEE00000;        // Local APIC MMIO base
const IOAPIC_BASE: u64 = 0xFEC00000;      // I/O APIC MMIO base

Interrupt Vectors


// CPU exceptions: 0-31
const DIV_BY_ZERO_VECTOR: u8 = 0;
const DEBUG_VECTOR: u8 = 1;
const PAGE_FAULT_VECTOR: u8 = 14;
const DOUBLE_FAULT_VECTOR: u8 = 8;

// Hardware interrupts: 32-255
const PIT_TIMER_VECTOR: u8 = 32;    // Legacy (disabled)
const KEYBOARD_VECTOR: u8 = 33;     // PS/2 keyboard
const VIRTIO_BLK_VECTOR: u8 = 34;   // VirtIO block device
const TIMER_VECTOR: u8 = 49;        // LAPIC timer

Calling Conventions

Rust (default)


Default for Rust-to-Rust calls

pub fn rust_function(arg: u32) -> u64 { }

C

For bootloader interface and assembly interop

pub extern "C" fn c_function(arg: u32) -> u64 { }

x86-interrupt

For CPU exception and hardware interrupt handlers


extern "x86-interrupt" fn handler(frame: InterruptStackFrame) { }

extern "x86-interrupt" fn handler_with_error(
) { }

Error Handling

Current Patterns

Panic


Used for unrecoverable programming errors

value.expect("Description of requirement") value.unwrap() panic!("Error message")

Oops

Used for hardware/CPU exceptions


util::panic::oops("Exception description")

Option


Used for nullable values

if let Some(value) = optional_value { } else { }


## Future: Result-Based APIs

Planned for post-v1.0

pub enum KernelError { }

pub type KernelResult = Result<T, KernelError>;

pub fn allocate_frame() -> KernelResult { }


## Future Extensions


## Planned API Additions

Memory Management
  • deallocate_frame() - Free physical frames
  • map_range() - Map multiple pages at once
  • protect_page() - Change page permissions (RO, RW, NX)
  • Memory statistics and pressure tracking

Task Management


- Preemptive scheduling with timer-based preemption
- task_sleep() - Sleep for duration
- task_block() - Block on condition variable
- task_wake() - Wake blocked task
- Process and thread creation API
- Priority inheritance for mutexes

Interrupt Management
  • register_irq_handler() - High-level IRQ registration
  • mask_irq() / unmask_irq() - Dynamic IRQ control
  • Interrupt statistics and profiling
  • MSI/MSI-X support

Device Management


- Device driver registration framework
- IOMMU support
- Power management (ACPI)

System Calls
  • File I/O: stat
  • Process management: fork, exec, wait, kill
  • Memory: mmap, munmap, mprotect, brk
  • IPC: pipe, socket, sendmsg, recvmsg
  • Signals: sigaction, kill, sigreturn

API Stability

Current Status: Pre-alpha (v0.0.6), APIs subject to change without notice

Versioning: Not yet established, will follow semantic versioning post-v1.0

Deprecation Policy: Not yet established

API Review: Comprehensive review required before v1.0 release

See Also

End of Document

See Also