]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
fix: deep audit — VA collision, arch pollution, broken stubs
authorTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 06:07:43 +0000 (03:07 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 06:07:43 +0000 (03:07 -0300)
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

12 files changed:
include/kernel_va_map.h [new file with mode: 0644]
src/arch/x86/acpi.c
src/arch/x86/ioapic.c
src/arch/x86/lapic.c
src/drivers/e1000.c
src/hal/x86/ata_dma.c
src/kernel/kconsole.c
src/kernel/syscall.c
src/kernel/tty.c
src/kernel/vdso.c
src/mm/pmm.c
src/net/e1000_netif.c

diff --git a/include/kernel_va_map.h b/include/kernel_va_map.h
new file mode 100644 (file)
index 0000000..e2a86ce
--- /dev/null
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2018, Tulio A M Mendes <[email protected]>
+ * All rights reserved.
+ * See LICENSE for details.
+ *
+ * Source: https://github.com/tadryanom/AdrOS
+ */
+
+#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
index 167381456539e368ab99a45ea674b43b3ad0ef7b..a90c69882528f982eebde1f608f540ca26172e30 100644 (file)
@@ -21,14 +21,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.
index f3c94ef89e54b7642610f7986942bfe60332f267..495d23460bc75b6c942d8c5f6bbd37d964c7089e 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "arch/x86/ioapic.h"
 #include "arch/x86/lapic.h"
+#include "kernel_va_map.h"
 #include "vmm.h"
 #include "console.h"
 #include "utils.h"
@@ -42,7 +43,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);
index 228bb49834c2fe8dce7c22a69104c0930e585668..18afdc89085ee06aa6258b640d71fa5eb597bc63 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include "arch/x86/lapic.h"
+#include "kernel_va_map.h"
 #include "hal/cpu_features.h"
 #include "vmm.h"
 #include "io.h"
@@ -100,7 +101,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;
index 61dc936a0e230dc103689059b81838d4853a4ef4..01cc0c5612c2b4a5a559019923a73da9fd9b5e14 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include "e1000.h"
+#include "kernel_va_map.h"
 #include "pci.h"
 #include "vmm.h"
 #include "pmm.h"
 
 #include <stddef.h>
 
-/* ------------------------------------------------------------------ */
-/* 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];
index 905a3c852ccf9efbed6d87f76da75ec7ee77cacc..e5da71a2f51039db55d066fa4d5d2554798f375f 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include "ata_dma.h"
+#include "kernel_va_map.h"
 #include "pci.h"
 #include "io.h"
 #include "pmm.h"
@@ -143,10 +144,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;
@@ -160,7 +159,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;
index 3e83e84ac2f38d6fc8a754b7258e3082ffa72812..99ebc19b9f674856a19495d73614544dcb3b93e5 100644 (file)
@@ -12,6 +12,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"
@@ -81,7 +82,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];
index 740c5d970dd8ce6d824a15a851c7b39e46132975..709ba0b829927b2a1910970e7ed3b31ea27951a8 100644 (file)
@@ -2204,11 +2204,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;
     }
index c34891ff7d4db2cc11c0943b716a64d24dc80ebd..eae854571ffdb5cfcd90f117fd79d29177312b00 100644 (file)
@@ -15,7 +15,6 @@
 #include "waitqueue.h"
 #include "spinlock.h"
 #include "console.h"
-#include "uart_console.h"
 #include "uaccess.h"
 #include "errno.h"
 
index 12bc12b18977125ca167911eb5cf52465937c13c..f80f6fa134d9e547fc868373b0c99cedb6e5ba7f 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include "vdso.h"
+#include "kernel_va_map.h"
 #include "pmm.h"
 #include "vmm.h"
 #include "utils.h"
@@ -24,9 +25,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);
 
index f655c1262cdf4eb63ccf70e2870817d4885d19b3..49496f2c0760d5ebef4ce40c9596f329281a425a 100644 (file)
@@ -253,3 +253,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));
+}
index a3a732e8911ae155fba1bbf6296f74f76df65742..1a0f4859ef8eebec95fa6b1a89d1cfdab3efe3f1 100644 (file)
@@ -21,6 +21,7 @@
 #include "lwip/tcpip.h"
 #include "lwip/sys.h"
 #include "netif/ethernet.h"
+#include "spinlock.h"
 
 #include "e1000.h"
 #include "console.h"
@@ -125,7 +126,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;