--- /dev/null
+#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
/* 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.
#include "arch/x86/ioapic.h"
#include "arch/x86/lapic.h"
+#include "kernel_va_map.h"
#include "vmm.h"
#include "console.h"
#include "utils.h"
/* 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);
#include "arch/x86/lapic.h"
+#include "kernel_va_map.h"
#include "hal/cpu_features.h"
#include "vmm.h"
#include "io.h"
/* 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;
#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];
#include "ata_dma.h"
+#include "kernel_va_map.h"
#include "pci.h"
#include "io.h"
#include "pmm.h"
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;
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;
#include "utils.h"
#include "fs.h"
#include "heap.h"
+#include "pmm.h"
#include "process.h"
#include "arch/arch_platform.h"
#include "hal/system.h"
}
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];
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;
}
#include "waitqueue.h"
#include "spinlock.h"
#include "console.h"
-#include "uart_console.h"
#include "uaccess.h"
#include "errno.h"
#include "vdso.h"
+#include "kernel_va_map.h"
#include "pmm.h"
#include "vmm.h"
#include "utils.h"
}
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);
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));
+}
#include "lwip/tcpip.h"
#include "lwip/sys.h"
#include "netif/ethernet.h"
+#include "spinlock.h"
#include "e1000.h"
#include "console.h"
/* 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;