diff --git a/audit.md b/audit.md new file mode 100644 index 0000000..2436ba5 --- /dev/null +++ b/audit.md @@ -0,0 +1,46 @@ +# Sovereign RTC64 Kernel - Security & Architectural Audit + +This document lists every identified flaw, potential vulnerability, and architectural weakness discovered during the industrial audit of the NEONT executive core. + +## 1. Critical Initialization & Boot Flaws +- **[Limine] Missing Request Markers:** The kernel is missing `LIMINE_REQUESTS_START_MARKER` and `LIMINE_REQUESTS_END_MARKER`. Without these, the bootloader fails to populate responses for HHDM, Memmap, and Framebuffer, resulting in a system-wide null-pointer cascade. +- **[Boot] HHDM Dependency:** The kernel assumes `hhdm_offset` is always valid. If the HHDM request fails, the kernel continues execution with `hhdm_offset = 0`, leading to incorrect virtual-to-physical mapping and Page Faults during driver initialization. +- **[PMM] Unsafe Bitmap Placement:** `pmm_init` does not verify if `hhdm_offset` is non-zero before calculating the virtual address for the physical bitmap. +- **[Heap] Silent Genesis Failure:** If `pmm_alloc_blocks` fails during heap creation, `hal_malloc_init` is called with a NULL pointer. This results in `global_tlsf_control` remaining NULL, causing all subsequent `malloc` calls to return NULL without error. + +## 2. Memory Management & Safety +- **[PMM] Inefficient Block Search:** `pmm_alloc_blocks` always starts searching from page 0 rather than using `pmm_last_alloc`, leading to $O(N)$ performance degradation. +- **[PMM] Lack of Initialization Guards:** Core functions like `pmm_alloc` do not verify if `pmm_bitmap` is non-null, leading to early boot null-pointer dereferences. +- **[Scrubbing] Direct PMM Leak:** While `tlsf_free` zeroes memory, memory requested via `pmm_alloc` directly (for DMA) is not zeroed, potentially leaking physical frame data between drivers. + +## 3. Concurrency & Synchronization +- **[VFS] Thread-Unsafe Resolver:** `vfs_resolve` uses a `static char res[256]` buffer. Concurrent calls from different tasks (e.g., Shell and App) will result in path corruption. +- **[Serial] Incomplete Syscall Locking:** The `SYS_SERIAL_WRITE` syscall routes directly to `serial_write`, bypassing the spinlock used by `serial_printf`. +- **[Storage] IO Race Conditions:** `ahci_io_wrapper` and `nvme_io_wrapper` use fixed command slots without per-device locking. Concurrent IO requests will corrupt the hardware command rings. + +## 4. Hardware Drivers +- **[AHCI] Virtual Address DMA:** The AHCI driver passes virtual buffers directly to the PRDT. The SATA controller (requiring physical addresses) will DMA into incorrect memory. +- **[EHCI] Incomplete Initialization:** The EHCI driver fails to initialize the Periodic or Asynchronous list base registers. USB transfers will never be processed by the hardware. +- **[PS/2] Blocking IO:** `ps2_wait_read` and `ps2_wait_write` are infinite loops without timeouts. A hardware failure will hang the entire kernel. +- **[xHCI] Slot Config Race:** The xHCI driver reads `HCSPARAMS1` and writes `CONFIG` without ensuring the controller is in a stable state for configuration. + +## 5. Scheduling & ABI +- **[Scheduler] Task Limit:** The kernel is hard-coded to 16 tasks. `scheduler_spawn` fails silently when the limit is reached. +- **[Scheduler] Delayed Stack Audit:** Stack overflow detection (canary check) only occurs in the Idle task once per second, leaving a large window for memory corruption. +- **[Syscall] Pointer Validation:** VFS syscalls do not verify if provided buffer pointers belong to the calling task's memory space. + +## 6. Graphics & UI +- **[VGA] Dirty Rect Missing:** `vga_log` performs a full-screen `memset` on wrap-around, causing visible flicker. No line-scrolling is implemented. +- **[Input] Coordinate Clamping:** `hal_input_push_event` accumulates mouse coordinates without clamping to screen dimensions, allowing the cursor to move into "ghost" memory. +- **[Framebuffer] Unprotected Access:** Multiple tasks (Environment Manager and VGA Log) can write to the framebuffer simultaneously without synchronization. + +## 7. Security & Policy +- **[UAC] Implementation Stubs:** `uac_request_permit` in `kernel/uac_policy.c` is currently a placeholder and does not actually perform security challenges or interrupt-based elevation. +- **[Panic] OSOD Recursion:** If `draw_glyph` or `memset` fails inside `osod_render`, the kernel may enter a recursive panic state without a hardware reset. +- **[VFS] FAT32 Auto-Format:** The VFS automatically formats uninitialized disks. This is a potential data-loss risk if a disk with a different filesystem is connected. + +## 8. 64-bit Architectural Risks +- **[Boot] Limine Request Markers:** Mandatory `LIMINE_REQUESTS_START_MARKER` and `LIMINE_REQUESTS_END_MARKER` are missing from the kernel entry point, which may cause Limine to ignore the executive's hardware requests (Memmap, HHDM, Framebuffer) on some versions. +- **[MMIO] Hardcoded APIC Address:** `APIC_BASE` is hardcoded to `0xFEE00000`. Industrial kernels should discover the local APIC address via the MP Table or ACPI MADT to ensure compatibility across diverse hardware. +- **[Paging] HHDM Assumption:** The kernel assumes a single `hhdm_offset` applies to all physical addresses. If the bootloader maps different regions with different offsets (unlikely but possible in Limine), the kernel logic will fail. +- **[CPU] Lack of Multi-core Support:** The kernel is strictly single-core. While spinlocks are implemented, they do not handle IPIs (Inter-Processor Interrupts) or cache coherency across multiple physical CPUs. diff --git a/include/hal.h b/include/hal.h index 682cd5f..e7ed838 100644 --- a/include/hal.h +++ b/include/hal.h @@ -120,4 +120,15 @@ void hal_usb_poll(void); void rtc_get_time(int *h, int *m, int *s); uint64_t hal_get_uptime_ms(void); +/* --- Synchronization --- */ +typedef volatile int spinlock_t; +static inline void spin_lock(spinlock_t *lock) { + while (__sync_lock_test_and_set(lock, 1)) { + __asm__ volatile("pause"); + } +} +static inline void spin_unlock(spinlock_t *lock) { + __sync_lock_release(lock); +} + #endif diff --git a/kernel/apic.c b/kernel/apic.c index 63b1e53..8d2a5b1 100644 --- a/kernel/apic.c +++ b/kernel/apic.c @@ -11,6 +11,7 @@ #define APIC_TMR 0x320 #define APIC_TDCR 0x3E0 #define APIC_TICR 0x380 +#define APIC_TCCR 0x390 extern uint64_t hhdm_offset; extern uint64_t scheduler_switch(uint64_t current_rsp); @@ -38,11 +39,25 @@ void apic_init(void) { /* Step 2: Calibrate Divider (Divide by 16) */ apic_write(APIC_TDCR, 0x03); - /* Step 3: Configure Timer (Vector 32, Periodic mode, start MASKED) */ - apic_write(APIC_TMR, 32 | 0x20000 | 0x10000); + /* Step 3: PIT-based Calibration for High-Power Precision */ + /* Set PIT to one-shot mode, approx 10ms (1193182 / 100) */ + outb(0x43, 0x30); + outb(0x40, 0x9B); + outb(0x40, 0x2E); + + apic_write(APIC_TICR, 0xFFFFFFFF); + + /* Wait for PIT to finish */ + while (1) { + outb(0x43, 0xE2); + if (inb(0x40) & 0x80) break; + } - /* Step 4: Set Initial Count */ - apic_write(APIC_TICR, 1000000); + uint32_t ticks_per_10ms = 0xFFFFFFFF - apic_read(APIC_TCCR); + + /* Step 4: Configure Timer (Vector 32, Periodic mode, start MASKED) */ + apic_write(APIC_TMR, 32 | 0x20000 | 0x10000); + apic_write(APIC_TICR, ticks_per_10ms); } uint64_t hal_get_uptime_ms(void) { diff --git a/kernel/drivers/pci.c b/kernel/drivers/pci.c index ef2ff2b..b362d45 100644 --- a/kernel/drivers/pci.c +++ b/kernel/drivers/pci.c @@ -23,6 +23,7 @@ typedef struct { #define MAX_PCI_DEVICES 64 static pci_device_info_t g_pci_devices[MAX_PCI_DEVICES]; static int g_pci_count = 0; +static spinlock_t g_pci_lock = 0; static uint32_t pci_read_config(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { uint32_t address = (uint32_t)((uint32_t)bus << 16) | ((uint32_t)slot << 11) | @@ -41,6 +42,7 @@ uint64_t pci_get_bar(uint8_t bus, uint8_t slot, uint8_t func, uint8_t bar_index) } void pci_scan(void) { + spin_lock(&g_pci_lock); serial_printf("[PCI] Starting system hardware scan...\n"); g_pci_count = 0; memset(g_pci_devices, 0, sizeof(g_pci_devices)); @@ -101,14 +103,20 @@ void pci_scan(void) { } } serial_printf("[PCI] Scan complete. Total devices: %d\n", g_pci_count); + spin_unlock(&g_pci_lock); } int pci_get_device_count(void) { return g_pci_count; } int pci_get_device_info(int index, char* buf, size_t sz) { - if (index < 0 || index >= g_pci_count) return -1; + spin_lock(&g_pci_lock); + if (index < 0 || index >= g_pci_count) { + spin_unlock(&g_pci_lock); + return -1; + } pci_device_info_t* d = &g_pci_devices[index]; snprintf(buf, sz, "V:%04X D:%04X C:%02X S:%02X P:%02X", d->vendor, d->device, d->class_id, d->subclass, d->prog_if); + spin_unlock(&g_pci_lock); return 0; } diff --git a/kernel/input.c b/kernel/input.c index ed6410d..b1b65f3 100644 --- a/kernel/input.c +++ b/kernel/input.c @@ -12,6 +12,7 @@ static input_event_t g_input_queue[INPUT_QUEUE_SIZE]; static volatile int g_queue_head = 0; static volatile int g_queue_tail = 0; +static spinlock_t g_input_lock = 0; static int g_mouse_abs_x = 0; static int g_mouse_abs_y = 0; @@ -57,6 +58,7 @@ bool hal_input_get_device_info(int index, input_device_info_t *info) { } void hal_input_push_event(input_event_t ev) { + spin_lock(&g_input_lock); int next = (g_queue_head + 1) % INPUT_QUEUE_SIZE; if (next != g_queue_tail) { g_input_queue[g_queue_head] = ev; @@ -66,12 +68,18 @@ void hal_input_push_event(input_event_t ev) { g_mouse_abs_x += ev.mouse.x; g_mouse_abs_y += ev.mouse.y; } + spin_unlock(&g_input_lock); } bool hal_input_pop_event(input_event_t *ev) { - if (g_queue_head == g_queue_tail) return false; + spin_lock(&g_input_lock); + if (g_queue_head == g_queue_tail) { + spin_unlock(&g_input_lock); + return false; + } *ev = g_input_queue[g_queue_tail]; g_queue_tail = (g_queue_tail + 1) % INPUT_QUEUE_SIZE; + spin_unlock(&g_input_lock); return true; } diff --git a/kernel/interrupts.c b/kernel/interrupts.c index 54c6c0e..2dca7c2 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -24,6 +24,16 @@ static idt_entry_t idt[256]; static idt_ptr_t idt_ptr; extern void* isr_stub_table[]; +extern void isr_stub_128(void); + +extern int syscall_dispatch(int num, const void* a1, void* a2, size_t a3); + +void syscall_handler(struct cpu_state* state) { + /* SYS_MALLOC and SYS_I18N_TRANSLATE return pointers, others return int. + * For simplicity in this skeleton, we route all through syscall_dispatch + * and store result in RAX. */ + state->rax = (uint64_t)syscall_dispatch((int)state->rax, (void*)state->rdi, (void*)state->rsi, (size_t)state->rdx); +} // Hardware exception gateways from panic.c extern void handler_divide_by_zero(void); @@ -53,6 +63,9 @@ void idt_init(void) { idt_set_gate(13, (uint64_t)handler_general_protection_fault, 0x08, 0x8E); idt_set_gate(14, (uint64_t)handler_page_fault, 0x08, 0x8E); + /* System Call Entry: Vector 0x80 */ + idt_set_gate(0x80, (uint64_t)isr_stub_128, 0x08, 0xEE); /* DPL=3 for user-space access */ + idt_ptr.limit = sizeof(idt) - 1; idt_ptr.base = (uint64_t)&idt; __asm__ volatile ("lidt %0" : : "m"(idt_ptr)); @@ -67,6 +80,10 @@ void irq_install_handler(int i, irq_handler_t handler) { extern void apic_eoi(void); void exception_handler(struct cpu_state *state) { + if (state->interrupt_number == 128) { + syscall_handler(state); + return; + } if (state->interrupt_number >= 32) { /* POWER: Centralized IRQ Acknowledgement */ if (irq_handlers[state->interrupt_number]) { diff --git a/kernel/isr_stubs.s b/kernel/isr_stubs.s index 61d86e9..5ff4583 100644 --- a/kernel/isr_stubs.s +++ b/kernel/isr_stubs.s @@ -75,6 +75,12 @@ irq 45 irq 46 irq 47 +.global isr_stub_128 +isr_stub_128: + pushq $0 + pushq $128 + jmp isr_common + isr_common: pushq %rax pushq %rbx @@ -154,7 +160,12 @@ isr_common: popq %rbx popq %rax addq $16, %rsp - iretq + /* ABI Integrity: Zero out scratch registers only if returning to user-space */ + testq $3, 8(%rsp) /* Check CS selector on stack for CPL3 */ + jz 1f + xorq %r11, %r11 + xorq %rcx, %rcx +1: iretq irq_common: pushq %rax @@ -240,7 +251,12 @@ irq_common: popq %rbx popq %rax addq $16, %rsp - iretq + /* ABI Integrity: Zero out scratch registers only if returning to user-space */ + testq $3, 8(%rsp) + jz 1f + xorq %r11, %r11 + xorq %rcx, %rcx +1: iretq .section .data .global isr_stub_table diff --git a/kernel/kernel.c b/kernel/kernel.c index c81471c..7bd693c 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -26,6 +26,11 @@ volatile struct limine_module_request module_request = { .revision = 0 }; +static volatile struct limine_memmap_request memmap_request = { + .id = LIMINE_MEMMAP_REQUEST, + .revision = 0 +}; + /* --- Global OS State --- */ uint64_t hhdm_offset = 0; struct limine_framebuffer *primary_fb = NULL; @@ -109,10 +114,16 @@ void kernel_main(void) { gdt_init(); idt_init(); - pmm_init(NULL); - hal_malloc_init(pmm_alloc_blocks(1024), 1024 * 4096); + if (memmap_request.response) { + pmm_init(memmap_request.response); + } + + /* Industrial Heap Genesis: Allocate physical blocks and map to virtual HHDM space */ + void* heap_phys = pmm_alloc_blocks(1024); + hal_malloc_init((void*)((uint64_t)heap_phys + hhdm_offset), 1024 * 4096); apic_init(); + irq_install_handler(32, timer_handler); init_sse(); scheduler_init(); diff --git a/kernel/malloc_glue.c b/kernel/malloc_glue.c index ab328bb..86393f2 100644 --- a/kernel/malloc_glue.c +++ b/kernel/malloc_glue.c @@ -4,6 +4,7 @@ #include static void* global_tlsf_control = NULL; +static spinlock_t g_malloc_lock = 0; void hal_malloc_init(void* mem, size_t bytes) { if (mem && bytes > 0) { @@ -16,15 +17,23 @@ void* tlsf_get_global(void) { } void* malloc(size_t size) { - return tlsf_malloc(global_tlsf_control, size); + spin_lock(&g_malloc_lock); + void* ptr = tlsf_malloc(global_tlsf_control, size); + spin_unlock(&g_malloc_lock); + return ptr; } void free(void* ptr) { + spin_lock(&g_malloc_lock); tlsf_free(global_tlsf_control, ptr); + spin_unlock(&g_malloc_lock); } void* realloc(void* ptr, size_t size) { - return tlsf_realloc(global_tlsf_control, ptr, size); + spin_lock(&g_malloc_lock); + void* res = tlsf_realloc(global_tlsf_control, ptr, size); + spin_unlock(&g_malloc_lock); + return res; } void* calloc(size_t nmemb, size_t size) { diff --git a/kernel/nuklear_kernel_impl.c b/kernel/nuklear_kernel_impl.c index 36fee7d..47ee8bb 100644 --- a/kernel/nuklear_kernel_impl.c +++ b/kernel/nuklear_kernel_impl.c @@ -145,6 +145,15 @@ void itoa_meaty(unsigned long long n, char* s, int base, bool neg, int width, ch if (neg) s[i++] = '-'; while (i < width) s[i++] = pad; s[i] = '\0'; reverse(s); + /* Correct padding logic: if pad is '0', the '-' should be at the front */ + if (neg && pad == '0' && width > 0) { + if (s[0] == '0') { + for (int j = 0; j < (int)strlen(s); j++) { + if (s[j] == '-') { s[j] = '0'; break; } + } + s[0] = '-'; + } + } } int vsnprintf(char* str, size_t size, const char* format, va_list ap) { @@ -183,6 +192,9 @@ int vsnprintf(char* str, size_t size, const char* format, va_list ap) { const char* s = buf; while (*s && i < size - 1) { char c = *s++; if (spec == 'X' && c >= 'a' && c <= 'z') c -= 32; str[i++] = c; } + } else if (*format == 'c') { + char c = (char)va_arg(ap, int); + str[i++] = c; } else if (*format == '%') { str[i++] = '%'; } else { /* Skip unknown */ } } else { str[i++] = *format; } diff --git a/kernel/pmm.c b/kernel/pmm.c index 9e1e134..1f48ca5 100644 --- a/kernel/pmm.c +++ b/kernel/pmm.c @@ -10,6 +10,7 @@ static uint64_t* pmm_bitmap = NULL; static uint64_t pmm_total_pages = 0; static uint64_t pmm_bitmap_size = 0; static uint64_t pmm_last_alloc = 0; +static spinlock_t pmm_lock = 0; void pmm_init(struct limine_memmap_response* map) { uint64_t top_address = 0; @@ -42,6 +43,10 @@ void pmm_init(struct limine_memmap_response* map) { } } + if (!pmm_bitmap) { + kpanic("PMM: Failed to place bitmap - no suitable usable memory block found."); + } + /* Mark usable pages as free in bitmap */ for (uint64_t i = 0; i < map->entry_count; i++) { struct limine_memmap_entry* en = map->entries[i]; @@ -68,10 +73,12 @@ static bool pmm_is_used(uint64_t page) { } void* pmm_alloc(void) { + spin_lock(&pmm_lock); for (uint64_t i = pmm_last_alloc; i < pmm_total_pages; i++) { if (!pmm_is_used(i)) { pmm_mark_used(i); pmm_last_alloc = i; + spin_unlock(&pmm_lock); return (void*)(i * PAGE_SIZE); } } @@ -80,22 +87,27 @@ void* pmm_alloc(void) { if (!pmm_is_used(i)) { pmm_mark_used(i); pmm_last_alloc = i; + spin_unlock(&pmm_lock); return (void*)(i * PAGE_SIZE); } } + spin_unlock(&pmm_lock); return NULL; } void* pmm_alloc_low(void) { + spin_lock(&pmm_lock); uint64_t max_page = 0x100000000ULL / PAGE_SIZE; if (max_page > pmm_total_pages) max_page = pmm_total_pages; for (uint64_t i = 0; i < max_page; i++) { if (!pmm_is_used(i)) { pmm_mark_used(i); + spin_unlock(&pmm_lock); return (void*)(i * PAGE_SIZE); } } + spin_unlock(&pmm_lock); return NULL; } @@ -103,6 +115,7 @@ void* pmm_alloc_blocks(size_t count) { if (count == 0) return NULL; if (count == 1) return pmm_alloc(); + spin_lock(&pmm_lock); for (uint64_t i = 0; i < pmm_total_pages - count; i++) { bool found = true; for (size_t j = 0; j < count; j++) { @@ -114,14 +127,17 @@ void* pmm_alloc_blocks(size_t count) { } if (found) { for (size_t j = 0; j < count; j++) pmm_mark_used(i + j); + spin_unlock(&pmm_lock); return (void*)(i * PAGE_SIZE); } } + spin_unlock(&pmm_lock); return NULL; } void* pmm_alloc_blocks_low(size_t count) { if (count == 0) return NULL; + spin_lock(&pmm_lock); uint64_t max_page = 0x100000000ULL / PAGE_SIZE; if (max_page > pmm_total_pages) max_page = pmm_total_pages; @@ -136,26 +152,32 @@ void* pmm_alloc_blocks_low(size_t count) { } if (found) { for (size_t j = 0; j < count; j++) pmm_mark_used(i + j); + spin_unlock(&pmm_lock); return (void*)(i * PAGE_SIZE); } } + spin_unlock(&pmm_lock); return NULL; } void pmm_free(void* addr) { if (!addr) return; + spin_lock(&pmm_lock); uint64_t page = (uint64_t)addr / PAGE_SIZE; if (page < pmm_total_pages) { pmm_mark_free(page); } + spin_unlock(&pmm_lock); } void pmm_free_blocks(void* addr, size_t count) { if (!addr) return; + spin_lock(&pmm_lock); uint64_t start_page = (uint64_t)addr / PAGE_SIZE; for (size_t i = 0; i < count; i++) { if (start_page + i < pmm_total_pages) { pmm_mark_free(start_page + i); } } + spin_unlock(&pmm_lock); } diff --git a/kernel/serial.c b/kernel/serial.c index a77e0b5..5bc34ec 100644 --- a/kernel/serial.c +++ b/kernel/serial.c @@ -6,6 +6,7 @@ #include "hal.h" #define COM1 0x3F8 +static spinlock_t g_serial_lock = 0; void serial_init(void) { outb(COM1 + 1, 0x00); @@ -31,12 +32,14 @@ void serial_write(const char* str) { } void serial_printf(const char* fmt, ...) { - char buf[512]; + spin_lock(&g_serial_lock); + char buf[1024]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); serial_write(buf); va_end(args); + spin_unlock(&g_serial_lock); } int serial_received(void) { diff --git a/kernel/syscall.c b/kernel/syscall.c index a870953..87e0833 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -6,15 +6,34 @@ #include "syscall_nums.h" #include "serial.h" +/* --- System Call Mapping Table (SCMT) Wrappers --- */ +static int sys_ls_w(const void* a1, void* a2, size_t a3) { return vfs_ls((const char*)a1, (char*)a2, a3); } +static int sys_cat_w(const void* a1, void* a2, size_t a3) { return vfs_cat((const char*)a1, (char*)a2, a3); } +static int sys_mkdir_w(const void* a1, void* a2, size_t a3) { (void)a2; (void)a3; return vfs_mkdir((const char*)a1); } +static int sys_write_w(const void* a1, void* a2, size_t a3) { (void)a3; return vfs_write((const char*)a1, (const char*)a2); } +static int sys_mounts_w(const void* a1, void* a2, size_t a3) { (void)a2; return vfs_get_mounts((char*)a1, a3); } +static int sys_devlist_w(const void* a1, void* a2, size_t a3) { (void)a2; return devmgr_list((char*)a1, a3); } +static int sys_free_w(const void* a1, void* a2, size_t a3) { (void)a2; (void)a3; free((void*)a1); return 0; } + +typedef int (*syscall_handler_t)(const void*, void*, size_t); + +static const syscall_handler_t scmt[] = { + [SYS_VFS_LS] = sys_ls_w, + [SYS_VFS_CAT] = sys_cat_w, + [SYS_VFS_MKDIR] = sys_mkdir_w, + [SYS_VFS_WRITE] = sys_write_w, + [SYS_VFS_MOUNTS] = sys_mounts_w, + [SYS_DEVMGR_LIST] = sys_devlist_w, + [SYS_FREE] = sys_free_w, +}; + int syscall_dispatch(int num, const void* a1, void* a2, size_t a3) { + /* Formal SCMT Dispatch */ + if (num > 0 && num <= SYS_FREE && scmt[num]) { + return scmt[num](a1, a2, a3); + } + switch (num) { - case SYS_VFS_LS: return vfs_ls((const char*)a1, (char*)a2, a3); - case SYS_VFS_CAT: return vfs_cat((const char*)a1, (char*)a2, a3); - case SYS_VFS_MKDIR: return vfs_mkdir((const char*)a1); - case SYS_VFS_WRITE: return vfs_write((const char*)a1, (const char*)a2); - case SYS_VFS_MOUNTS: return vfs_get_mounts((char*)a1, a3); - case SYS_DEVMGR_LIST: return devmgr_list((char*)a1, a3); - case SYS_FREE: free((void*)a1); return 0; case SYS_GET_UPTIME: *(uint64_t*)a2 = hal_get_uptime_ms(); return 0; case SYS_GET_CPU_LOAD: return scheduler_get_cpu_load(); case SYS_SPAWN: return scheduler_spawn((const char*)a1, (void (*)(void*))a2, (void*)a3); diff --git a/kernel/tlsf_impl.c b/kernel/tlsf_impl.c index e9dc975..49a18d9 100644 --- a/kernel/tlsf_impl.c +++ b/kernel/tlsf_impl.c @@ -115,6 +115,10 @@ void tlsf_free(void* tlsf_ptr, void* ptr) { tlsf_control_t* t = (tlsf_control_t*)tlsf_ptr; block_header_t* block = (block_header_t*)((uint8_t*)ptr - sizeof(block_header_t)); size_t block_size = block->size & BLOCK_SIZE_MASK; + + /* Industrial Scrubbing: Zero out memory before deallocation */ + memset(ptr, 0, block_size); + t->used_size -= (block_size + sizeof(block_header_t)); block->size |= BLOCK_FREE_BIT; @@ -168,6 +172,9 @@ void* tlsf_realloc(void* tlsf, void* ptr, size_t size) { /* MEATY: Metric Accessors */ size_t hal_malloc_get_used(void) { + /* Metric accessors are inherently non-atomic but we use the global control. + * We don't lock here to avoid deadlock if called during malloc debug logs. + */ tlsf_control_t* t = (tlsf_control_t*)tlsf_get_global(); return t ? t->used_size : 0; } diff --git a/kernel/usb_osal.c b/kernel/usb_osal.c index 9888893..cf817d4 100644 --- a/kernel/usb_osal.c +++ b/kernel/usb_osal.c @@ -2,6 +2,7 @@ * Licensed under the 'respect people's property' OS license. */ /* Modified by Sovereign: Robust OSAL implementation for CherryUSB with interrupt-safe critical sections */ #include "usb_osal.h" +#include "pro_os.h" #include "hal.h" #include "external/tlsf.h" #include @@ -44,16 +45,14 @@ void usb_osal_leave_critical_section(size_t flag) { ); } -extern void scheduler_add_task(const char *name, void (*entry)(void)); - usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t priority, usb_thread_entry_t entry, void *argument) { - (void)stack_size; (void)priority; (void)argument; + (void)stack_size; (void)priority; serial_printf("[USB OSAL] Creating thread: %s\n", name); if (entry) { /* MEATY: Registering with kernel scheduler for true multitasking */ - scheduler_add_task(name, (void (*)(void))entry); + int tid = scheduler_spawn(name, (void (*)(void*))entry, argument); /* In this freestanding implementation, we pass the task ID as thread handle */ - return (usb_osal_thread_t)1; + return (usb_osal_thread_t)(uintptr_t)tid; } return (usb_osal_thread_t)NULL; } @@ -89,11 +88,10 @@ int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout) { usb_sem_t *s = (usb_sem_t *)sem; if (!s) return -1; - uint32_t start_time = 0; // Simplified + uint64_t start_ms = hal_get_uptime_ms(); while (s->count == 0) { - if (timeout != 0xFFFFFFFFU && start_time >= timeout) return -1; - __asm__("pause"); - start_time++; // Dummy increment + if (timeout != 0xFFFFFFFFU && (hal_get_uptime_ms() - start_ms >= timeout)) return -1; + scheduler_yield(); } size_t flags = usb_osal_enter_critical_section(); @@ -185,11 +183,10 @@ int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout) { usb_mq_t *m = (usb_mq_t *)mq; if (!m || !addr) return -1; - uint32_t wait = 0; + uint64_t start_ms = hal_get_uptime_ms(); while (m->head == m->tail) { - if (timeout != 0xFFFFFFFFU && wait >= timeout) return -1; - __asm__("pause"); - wait++; + if (timeout != 0xFFFFFFFFU && (hal_get_uptime_ms() - start_ms >= timeout)) return -1; + scheduler_yield(); } size_t flags = usb_osal_enter_critical_section(); @@ -226,9 +223,9 @@ void usb_osal_timer_stop(struct usb_osal_timer *timer) { } void usb_osal_msleep(uint32_t delay) { - /* MEATY: Calibrated delay loop for x86-64 */ - for (uint32_t i = 0; i < delay; i++) { - for (volatile uint32_t j = 0; j < 1000000; j++) __asm__("pause"); + uint64_t start_ms = hal_get_uptime_ms(); + while (hal_get_uptime_ms() - start_ms < delay) { + scheduler_yield(); } } diff --git a/kernel/vga_log.c b/kernel/vga_log.c index 9fe8aa7..7e518d5 100644 --- a/kernel/vga_log.c +++ b/kernel/vga_log.c @@ -74,9 +74,12 @@ static const uint8_t font8x8[128][8] = { ['Z'] = {0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00}, }; +extern uint64_t hhdm_offset; + void draw_glyph(int x, int y, char c, uint32_t color) { if (!primary_fb) return; - uint8_t *fb = (uint8_t*)primary_fb->address; + /* Industrial Alignment: Always use HHDM-adjusted virtual address for direct framebuffer access */ + uint8_t *fb = (uint8_t*)((uint64_t)primary_fb->address + hhdm_offset); const uint8_t *glyph = font8x8[(uint8_t)c]; for (int gy = 0; gy < 8; gy++) { if (y + gy >= (int)primary_fb->height) break; @@ -92,6 +95,7 @@ void draw_glyph(int x, int y, char c, uint32_t color) { void vga_log(const char* str) { if (!vga_enabled || !primary_fb) return; + uint8_t *fb_virt = (uint8_t*)((uint64_t)primary_fb->address + hhdm_offset); while (*str) { if (*str == '\n') { term_x = 0; term_y += 10; @@ -105,7 +109,7 @@ void vga_log(const char* str) { } } if (term_y >= (int)primary_fb->height - 10) { - memset((void*)primary_fb->address, 0, primary_fb->height * primary_fb->pitch); + memset((void*)fb_virt, 0, primary_fb->height * primary_fb->pitch); term_x = 0; term_y = 0; } str++; @@ -115,6 +119,7 @@ void vga_log(const char* str) { void vga_disable_log(void) { vga_enabled = 0; if (primary_fb) { - memset((void*)primary_fb->address, 0, primary_fb->height * primary_fb->pitch); + uint8_t *fb_virt = (uint8_t*)((uint64_t)primary_fb->address + hhdm_offset); + memset((void*)fb_virt, 0, primary_fb->height * primary_fb->pitch); } }