From: Tulio A M Mendes Date: Fri, 13 Feb 2026 06:07:43 +0000 (-0300) Subject: fix: deep audit — VA collision, arch pollution, broken stubs X-Git-Url: https://projects.tadryanom.me/docs/static/git-favicon.png?a=commitdiff_plain;h=71fe7ad382d1c12efa3d85c4a9e544c0e88d1160;p=AdrOS.git fix: deep audit — VA collision, arch pollution, broken stubs Critical bug fix: - VDSO and E1000 both mapped at VA 0xC0230000 — silent corruption! VDSO moved to 0xC0280000, E1000 moved to 0xC0330000-0xC0371FFF New centralized VA map (include/kernel_va_map.h): - All fixed kernel VA allocations documented in one header - IOAPIC, VDSO, ACPI, ATA DMA, E1000, LAPIC all use KVA_* defines - Prevents future VA collisions — single source of truth Architecture pollution fixes: - syscall.c SET_THREAD_AREA: replaced x86 gdt_set_gate_ext() with hal_cpu_set_tls() HAL call (was #if __i386__ inline) - e1000_netif.c: replaced x86 'pause' asm with cpu_relax() from spinlock.h (arch-agnostic) - tty.c: removed dead uart_console.h include (switched to console_put_char in previous commit) Broken code fix: - pmm_print_stats(): was declared in pmm.h but never implemented — now prints Total/Used/Free RAM in KB and MB - kconsole 'mem' command: replaced [TODO] stub with pmm_print_stats() Files using centralized KVA_* defines: - vdso.c, e1000.c, acpi.c, ata_dma.c, ioapic.c, lapic.c Build: clean, cppcheck: clean, smoke: 19/19 pass --- diff --git a/include/kernel_va_map.h b/include/kernel_va_map.h new file mode 100644 index 0000000..b1c462e --- /dev/null +++ b/include/kernel_va_map.h @@ -0,0 +1,54 @@ +#ifndef KERNEL_VA_MAP_H +#define KERNEL_VA_MAP_H + +/* + * Centralized kernel virtual address map for MMIO / DMA / special regions. + * + * All fixed-VA allocations MUST be listed here to prevent collisions. + * The kernel image is loaded at KERNEL_VIRT_BASE (0xC0000000) and BSS + * can extend past 0xC0200000 with large static pools (lwIP, FAT, etc.). + * + * Layout (sorted by VA): + * + * 0xC0000000 .. ~0xC0203000 Kernel .text/.data/.bss (variable) + * 0xC0201000 IOAPIC MMIO (1 page) + * 0xC0280000 vDSO shared page (1 page) + * 0xC0300000 .. 0xC030FFFF ACPI temp window (16 pages) + * 0xC0320000 ATA DMA PRDT (1 page) + * 0xC0321000 ATA DMA bounce buffer (1 page) + * 0xC0330000 .. 0xC034FFFF E1000 MMIO (32 pages, 128 KB) + * 0xC0350000 E1000 TX descriptor ring (1 page) + * 0xC0351000 E1000 RX descriptor ring (1 page) + * 0xC0352000 .. 0xC0361FFF E1000 TX buffers (16 pages) + * 0xC0362000 .. 0xC0371FFF E1000 RX buffers (16 pages) + * 0xC0400000 LAPIC MMIO (1 page) + * 0xC8000000 .. Kernel stacks (guard + 8KB per thread) + * 0xD0000000 .. Kernel heap (10 MB) + */ + +/* IOAPIC (arch/x86/ioapic.c) */ +#define KVA_IOAPIC 0xC0201000U + +/* vDSO shared page (kernel/vdso.c) */ +#define KVA_VDSO 0xC0280000U + +/* ACPI temp mapping window — 16 pages (arch/x86/acpi.c) */ +#define KVA_ACPI_TMP_BASE 0xC0300000U +#define KVA_ACPI_TMP_PAGES 16 + +/* ATA DMA (hal/x86/ata_dma.c) */ +#define KVA_ATA_DMA_PRDT 0xC0320000U +#define KVA_ATA_DMA_BUF 0xC0321000U + +/* E1000 NIC (drivers/e1000.c) */ +#define KVA_E1000_MMIO 0xC0330000U +#define KVA_E1000_MMIO_PAGES 32 +#define KVA_E1000_TX_DESC 0xC0350000U +#define KVA_E1000_RX_DESC 0xC0351000U +#define KVA_E1000_TX_BUF 0xC0352000U +#define KVA_E1000_RX_BUF 0xC0362000U + +/* LAPIC (arch/x86/lapic.c) */ +#define KVA_LAPIC 0xC0400000U + +#endif diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c index 26367af..eef6da6 100644 --- a/src/arch/x86/acpi.c +++ b/src/arch/x86/acpi.c @@ -12,14 +12,14 @@ static int g_acpi_valid = 0; /* The first 16MB is identity-mapped during early boot (boot.S maps 0-16MB). * For addresses < 16MB we can use phys + 0xC0000000. * For addresses >= 16MB we must temporarily map them via VMM. */ +#include "kernel_va_map.h" + #define KERNEL_VIRT_BASE 0xC0000000U #define IDENTITY_LIMIT 0x01000000U /* 16MB */ -/* Temporary VA window for mapping ACPI tables above the identity-mapped range. - * We use up to 16 pages (64KB) starting at a fixed VA well above BSS _end. - * BSS can grow past 0xC0200000 with lwIP memp pools + FAT driver statics. */ -#define ACPI_TMP_VA_BASE 0xC0300000U -#define ACPI_TMP_VA_PAGES 16 +/* Temporary VA window for ACPI tables — see include/kernel_va_map.h */ +#define ACPI_TMP_VA_BASE KVA_ACPI_TMP_BASE +#define ACPI_TMP_VA_PAGES KVA_ACPI_TMP_PAGES static uint32_t acpi_tmp_mapped = 0; /* bitmask of which pages are mapped */ /* Map a physical address and return a usable virtual pointer. diff --git a/src/arch/x86/ioapic.c b/src/arch/x86/ioapic.c index e4d9a14..6778c1d 100644 --- a/src/arch/x86/ioapic.c +++ b/src/arch/x86/ioapic.c @@ -1,5 +1,6 @@ #include "arch/x86/ioapic.h" #include "arch/x86/lapic.h" +#include "kernel_va_map.h" #include "vmm.h" #include "console.h" #include "utils.h" @@ -33,7 +34,7 @@ int ioapic_init(void) { /* Map IOAPIC MMIO region. * Default base is 0xFEC00000. In the future, ACPI MADT will provide this. */ uintptr_t phys_base = IOAPIC_DEFAULT_BASE; - uintptr_t ioapic_va = 0xC0201000U; /* Fixed kernel VA, above _end */ + uintptr_t ioapic_va = KVA_IOAPIC; vmm_map_page((uint64_t)phys_base, (uint64_t)ioapic_va, VMM_FLAG_PRESENT | VMM_FLAG_RW | VMM_FLAG_NOCACHE); diff --git a/src/arch/x86/lapic.c b/src/arch/x86/lapic.c index e459443..2d6a0d8 100644 --- a/src/arch/x86/lapic.c +++ b/src/arch/x86/lapic.c @@ -1,4 +1,5 @@ #include "arch/x86/lapic.h" +#include "kernel_va_map.h" #include "hal/cpu_features.h" #include "vmm.h" #include "io.h" @@ -91,7 +92,7 @@ int lapic_init(void) { /* Map LAPIC MMIO region into kernel virtual address space. * Use a fixed kernel VA for the LAPIC page. */ - uintptr_t lapic_va = 0xC0400000U; /* Fixed kernel VA, well above _end */ + uintptr_t lapic_va = KVA_LAPIC; vmm_map_page((uint64_t)phys_base, (uint64_t)lapic_va, VMM_FLAG_PRESENT | VMM_FLAG_RW | VMM_FLAG_NOCACHE); lapic_base = (volatile uint32_t*)lapic_va; diff --git a/src/drivers/e1000.c b/src/drivers/e1000.c index 346f876..551a2cd 100644 --- a/src/drivers/e1000.c +++ b/src/drivers/e1000.c @@ -1,4 +1,5 @@ #include "e1000.h" +#include "kernel_va_map.h" #include "pci.h" #include "vmm.h" #include "pmm.h" @@ -9,20 +10,13 @@ #include -/* ------------------------------------------------------------------ */ -/* Kernel VA layout for E1000 DMA buffers */ -/* 0xC0230000 .. 0xC024FFFF E1000 MMIO (128 KB = 32 pages) */ -/* 0xC0250000 TX descriptor ring (1 page) */ -/* 0xC0251000 RX descriptor ring (1 page) */ -/* 0xC0252000 .. 0xC0261FFF TX buffers (32 x 2 KB = 16 pages) */ -/* 0xC0262000 .. 0xC0271FFF RX buffers (32 x 2 KB = 16 pages) */ -/* ------------------------------------------------------------------ */ -#define E1000_MMIO_VA 0xC0230000U -#define E1000_MMIO_PAGES 32 -#define E1000_TX_DESC_VA 0xC0250000U -#define E1000_RX_DESC_VA 0xC0251000U -#define E1000_TX_BUF_VA 0xC0252000U -#define E1000_RX_BUF_VA 0xC0262000U +/* Kernel VA layout for E1000 DMA buffers — see include/kernel_va_map.h */ +#define E1000_MMIO_VA KVA_E1000_MMIO +#define E1000_MMIO_PAGES KVA_E1000_MMIO_PAGES +#define E1000_TX_DESC_VA KVA_E1000_TX_DESC +#define E1000_RX_DESC_VA KVA_E1000_RX_DESC +#define E1000_TX_BUF_VA KVA_E1000_TX_BUF +#define E1000_RX_BUF_VA KVA_E1000_RX_BUF static volatile uint32_t* e1000_mmio = 0; static uint8_t e1000_mac[6]; diff --git a/src/hal/x86/ata_dma.c b/src/hal/x86/ata_dma.c index 5cc3370..896a625 100644 --- a/src/hal/x86/ata_dma.c +++ b/src/hal/x86/ata_dma.c @@ -1,4 +1,5 @@ #include "ata_dma.h" +#include "kernel_va_map.h" #include "pci.h" #include "io.h" #include "pmm.h" @@ -134,10 +135,8 @@ int ata_dma_init(void) { return -ENOMEM; } prdt_phys = (uint32_t)(uintptr_t)prdt_page; - /* Map PRDT at a dedicated VA to avoid collisions with the heap. - * 0xC0320000 is above LAPIC(0xC0400000), IOAPIC(0xC0201000), - * and ACPI temp window (0xC0300000-0xC0310000). */ - uintptr_t prdt_virt = 0xC0320000U; + /* Map PRDT at a dedicated VA — see include/kernel_va_map.h */ + uintptr_t prdt_virt = KVA_ATA_DMA_PRDT; vmm_map_page((uint64_t)prdt_phys, (uint64_t)prdt_virt, VMM_FLAG_PRESENT | VMM_FLAG_RW); prdt = (struct prd_entry*)prdt_virt; @@ -151,7 +150,7 @@ int ata_dma_init(void) { return -ENOMEM; } dma_buf_phys = (uint32_t)(uintptr_t)buf_page; - uintptr_t buf_virt = 0xC0321000U; + uintptr_t buf_virt = KVA_ATA_DMA_BUF; vmm_map_page((uint64_t)dma_buf_phys, (uint64_t)buf_virt, VMM_FLAG_PRESENT | VMM_FLAG_RW); dma_buf = (uint8_t*)buf_virt; diff --git a/src/kernel/kconsole.c b/src/kernel/kconsole.c index 8e21a6d..6eb7ec4 100644 --- a/src/kernel/kconsole.c +++ b/src/kernel/kconsole.c @@ -3,6 +3,7 @@ #include "utils.h" #include "fs.h" #include "heap.h" +#include "pmm.h" #include "process.h" #include "arch/arch_platform.h" #include "hal/system.h" @@ -72,7 +73,7 @@ static void kconsole_exec(const char* cmd) { } else if (strcmp(cmd, "mem") == 0) { kprintf("Memory Stats:\n"); - kprintf(" Total RAM: [TODO] MB\n"); + pmm_print_stats(); } else if (strcmp(cmd, "dmesg") == 0) { char buf[4096]; diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 4ce9f30..1da65bb 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -2195,11 +2195,7 @@ void syscall_handler(struct registers* regs) { uintptr_t base = (uintptr_t)sc_arg0(regs); if (!current_process) { sc_ret(regs) = (uint32_t)-EINVAL; return; } current_process->tls_base = base; -#if defined(__i386__) - extern void gdt_set_gate_ext(int num, uint32_t base, uint32_t limit, - uint8_t access, uint8_t gran); - gdt_set_gate_ext(22, (uint32_t)base, 0xFFFFF, 0xF2, 0xCF); -#endif + hal_cpu_set_tls(base); sc_ret(regs) = 0; return; } diff --git a/src/kernel/tty.c b/src/kernel/tty.c index 7fec5f8..2f6217b 100644 --- a/src/kernel/tty.c +++ b/src/kernel/tty.c @@ -6,7 +6,6 @@ #include "waitqueue.h" #include "spinlock.h" #include "console.h" -#include "uart_console.h" #include "uaccess.h" #include "errno.h" diff --git a/src/kernel/vdso.c b/src/kernel/vdso.c index 74a9ae1..ed09350 100644 --- a/src/kernel/vdso.c +++ b/src/kernel/vdso.c @@ -1,4 +1,5 @@ #include "vdso.h" +#include "kernel_va_map.h" #include "pmm.h" #include "vmm.h" #include "utils.h" @@ -15,9 +16,8 @@ void vdso_init(void) { } vdso_phys = (uintptr_t)page; - /* Map into kernel space at a fixed VA so we can write to it. - * Use 0xC0230000 (above ATA DMA bounce at 0xC0221000). */ - uintptr_t kva = 0xC0230000U; + /* Map into kernel space at a fixed VA so we can write to it. */ + uintptr_t kva = KVA_VDSO; vmm_map_page((uint64_t)vdso_phys, (uint64_t)kva, VMM_FLAG_PRESENT | VMM_FLAG_RW); diff --git a/src/mm/pmm.c b/src/mm/pmm.c index e9e5615..5fdbd71 100644 --- a/src/mm/pmm.c +++ b/src/mm/pmm.c @@ -244,3 +244,15 @@ uint16_t pmm_get_refcount(uintptr_t paddr) { spin_unlock_irqrestore(&pmm_lock, flags); return rc; } + +void pmm_print_stats(void) { + uintptr_t flags = spin_lock_irqsave(&pmm_lock); + uint64_t total_kb = total_memory / 1024; + uint64_t used_kb = used_memory / 1024; + uint64_t free_kb = (total_memory > used_memory) ? (total_memory - used_memory) / 1024 : 0; + spin_unlock_irqrestore(&pmm_lock, flags); + + kprintf(" Total RAM: %u KB (%u MB)\n", (unsigned)total_kb, (unsigned)(total_kb / 1024)); + kprintf(" Used: %u KB (%u MB)\n", (unsigned)used_kb, (unsigned)(used_kb / 1024)); + kprintf(" Free: %u KB (%u MB)\n", (unsigned)free_kb, (unsigned)(free_kb / 1024)); +} diff --git a/src/net/e1000_netif.c b/src/net/e1000_netif.c index 0d5d8d4..03e0f07 100644 --- a/src/net/e1000_netif.c +++ b/src/net/e1000_netif.c @@ -12,6 +12,7 @@ #include "lwip/tcpip.h" #include "lwip/sys.h" #include "netif/ethernet.h" +#include "spinlock.h" #include "e1000.h" #include "console.h" @@ -116,7 +117,7 @@ void net_init(void) { /* Start lwIP tcpip thread and poll until it signals ready */ tcpip_init(net_init_done, NULL); while (!tcpip_ready) { - __asm__ volatile("pause" ::: "memory"); + cpu_relax(); } ip4_addr_t ipaddr, netmask, gw;