]> 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..b1c462e
--- /dev/null
@@ -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
index 26367aff5e0113c55e40ef39d93407d24a5ff0e5..eef6da61fe19b2293a15f56f11ab45e54aada043 100644 (file)
@@ -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.
index e4d9a14beadd64e8333bc9b856936e7e3d47cd5e..6778c1d0bbe02120436873608ed5ccec8cf58b4a 100644 (file)
@@ -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);
index e45944306edd5afd00187cb8d597b86e29e1bdf0..2d6a0d8567d404c56e35457cd5cc043745a0ce30 100644 (file)
@@ -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;
index 346f876ed18e95e3e54ad802bb49126cc770e084..551a2cdad47ba46ff6ff100edb9339659e27ce46 100644 (file)
@@ -1,4 +1,5 @@
 #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 5cc337092f80d4633cb3f1530f98ed2b3e999f75..896a625de40dcd803c95b06c0c4df0fa0b1195c7 100644 (file)
@@ -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;
index 8e21a6db6b52f89f011290eed7c3432c71e301e8..6eb7ec4f516a65e91e646aece9e4ecc3d6364d54 100644 (file)
@@ -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];
index 4ce9f30aafd599abafa529d4387266e7fce91b7b..1da65bb4b4f43b50951a3bdef0f4b87f071f4dd9 100644 (file)
@@ -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;
     }
index 7fec5f84ac924e8aa8798f1bc267e2469277fa1c..2f6217bcb1d9f0f94053c04b0f887ed8fb2c807a 100644 (file)
@@ -6,7 +6,6 @@
 #include "waitqueue.h"
 #include "spinlock.h"
 #include "console.h"
-#include "uart_console.h"
 #include "uaccess.h"
 #include "errno.h"
 
index 74a9ae1e725015aeb617e1619ed111f398bc3795..ed09350beae5f425f0f4ad8ff648edb52db49559 100644 (file)
@@ -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);
 
index e9e5615a26c2a983b8adfd8a87958158555fc806..5fdbd71ff23e81e48e97d624f2685331428ef625 100644 (file)
@@ -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));
+}
index 0d5d8d45830f31ef44af37e254a7b90b677c7e34..03e0f074302757d5b1e323b2ef09b2df587c19c4 100644 (file)
@@ -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;