* 0xC0362000 .. 0xC0371FFF E1000 RX buffers (16 pages)
* 0xC0400000 LAPIC MMIO (1 page)
* 0xC0401000 IOAPIC MMIO (1 page)
+ * 0xC0500000 .. 0xC0800000 KVA allocator (dynamic VA, 3 MB)
* 0xC8000000 .. Kernel stacks (guard + 8KB per thread)
* 0xD0000000 .. Kernel heap (10 MB)
- * 0xDC000000 .. Initrd / generic phys mapping (up to 64 MB)
* 0xE0000000 .. Framebuffer mapping (up to 16 MB)
*/
/* LAPIC (arch/x86/lapic.c) */
#define KVA_LAPIC 0xC0400000U
-/* Initrd / generic physical range mapping (hal/x86/mm.c) */
-#define KVA_PHYS_MAP 0xDC000000U
-
/* Framebuffer (drivers/vbe.c) — up to 16 MB for large resolutions */
#define KVA_FRAMEBUFFER 0xE0000000U
--- /dev/null
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * All rights reserved.
+ * See LICENSE for details.
+ *
+ * Source: https://github.com/tadryanom/AdrOS
+ */
+
+#ifndef KVA_ALLOC_H
+#define KVA_ALLOC_H
+
+#include <stdint.h>
+
+/*
+ * Kernel Virtual Address Allocator
+ *
+ * Dynamically allocates virtual address ranges for MMIO/DMA/temporary mappings.
+ * Replaces fixed VAs like KVA_PHYS_MAP and VIRTIO_VRING_VA.
+ *
+ * Allocator region: 0xC0500000 .. 0xC0800000 (3 MB, 768 pages)
+ * - Below 0xC0500000: Fixed MMIO regions (ACPI, ATA, E1000, LAPIC, IOAPIC)
+ * - Above 0xC0800000: Kernel stacks, heap, initrd, framebuffer
+ */
+
+/* Initialize the KVA allocator */
+void kva_alloc_init(void);
+
+/* Allocate a contiguous range of pages (returns 0 on failure) */
+uintptr_t kva_alloc_pages(uint32_t page_count);
+
+/* Free a previously allocated range */
+void kva_free_pages(uintptr_t virt, uint32_t page_count);
+
+#endif
#include "spinlock.h"
#include "pmm.h"
#include "vmm.h"
+#include "kva_alloc.h"
#include "interrupts.h"
#include "hal/driver.h"
#include "io.h"
uint32_t total = vring_size(vblk_queue_size);
uint32_t pages = (total + 4095U) / 4096U;
- /* Use a fixed VA range for virtio vring */
- #define VIRTIO_VRING_VA 0xC0340000U
+ /* Use dynamic VA allocation for virtio vring */
+ uintptr_t vring_va = kva_alloc_pages(pages);
+ if (vring_va == 0) {
+ kprintf("[VIRTIO-BLK] Failed to allocate vring VA.\n");
+ outb(vblk_iobase + VIRTIO_PCI_STATUS, VIRTIO_STATUS_FAILED);
+ return -1;
+ }
+
for (uint32_t i = 0; i < pages; i++) {
void* frame = pmm_alloc_page();
if (!frame) {
return -1;
}
vmm_map_page((uint64_t)(uintptr_t)frame,
- (uint64_t)(VIRTIO_VRING_VA + i * 4096U),
+ (uint64_t)(vring_va + i * 4096U),
VMM_FLAG_PRESENT | VMM_FLAG_RW | VMM_FLAG_NOCACHE);
}
- memset((void*)VIRTIO_VRING_VA, 0, pages * 4096U);
+ memset((void*)vring_va, 0, pages * 4096U);
/* Set up vring pointers */
- vblk_desc = (struct vring_desc*)VIRTIO_VRING_VA;
+ vblk_desc = (struct vring_desc*)vring_va;
uint32_t avail_off = vblk_queue_size * (uint32_t)sizeof(struct vring_desc);
- vblk_avail = (struct vring_avail*)(VIRTIO_VRING_VA + avail_off);
+ vblk_avail = (struct vring_avail*)(vring_va + avail_off);
uint32_t used_off = avail_off + sizeof(uint16_t) * (3 + vblk_queue_size);
used_off = (used_off + 4095U) & ~4095U;
- vblk_used = (struct vring_used*)(VIRTIO_VRING_VA + used_off);
+ vblk_used = (struct vring_used*)(vring_va + used_off);
vblk_last_used_idx = 0;
/* Tell device where the vring lives (page-aligned physical address) */
- uint32_t vring_phys = (uint32_t)V2P(VIRTIO_VRING_VA);
+ uint32_t vring_phys = (uint32_t)V2P(vring_va);
outl(vblk_iobase + VIRTIO_PCI_QUEUE_PFN, vring_phys / 4096U);
/* Mark driver ready */
#include "vmm.h"
#include "arch/x86/kernel_va_map.h"
+#include "kva_alloc.h"
#include <stddef.h>
if (phys_end < phys_start) phys_end = phys_start;
- const uintptr_t virt_base = KVA_PHYS_MAP;
-
uintptr_t phys_start_aligned = phys_start & ~(uintptr_t)0xFFF;
uintptr_t phys_end_aligned = (phys_end + 0xFFF) & ~(uintptr_t)0xFFF;
uintptr_t size = phys_end_aligned - phys_start_aligned;
uintptr_t pages = size >> 12;
+ /* Allocate dynamic VA range instead of using fixed KVA_PHYS_MAP */
+ uintptr_t virt_base = kva_alloc_pages((uint32_t)pages);
+ if (virt_base == 0) {
+ return -1;
+ }
+
uint32_t vmm_flags = VMM_FLAG_PRESENT;
if (flags & HAL_MM_MAP_RW) vmm_flags |= VMM_FLAG_RW;
--- /dev/null
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * All rights reserved.
+ * See LICENSE for details.
+ *
+ * Source: https://github.com/tadryanom/AdrOS
+ */
+
+#include "kva_alloc.h"
+
+#include "console.h"
+#include "hal/cpu.h"
+#include "spinlock.h"
+
+#include <stddef.h>
+#include <string.h>
+
+/* Allocator region: 0xC0500000 .. 0xC0800000 (3 MB, 768 pages) */
+#define KVA_ALLOC_BASE 0xC0500000U
+#define KVA_ALLOC_END 0xC0800000U
+#define KVA_ALLOC_PAGES ((KVA_ALLOC_END - KVA_ALLOC_BASE) >> 12)
+
+/* Bitmap for allocation tracking (1 bit per page) */
+static uint8_t g_kva_bitmap[KVA_ALLOC_PAGES / 8];
+static spinlock_t g_kva_lock;
+
+void kva_alloc_init(void) {
+ memset(g_kva_bitmap, 0, sizeof(g_kva_bitmap));
+ spinlock_init(&g_kva_lock);
+}
+
+static inline void bitmap_set(uint32_t bit) {
+ g_kva_bitmap[bit >> 3] |= (1 << (bit & 7));
+}
+
+static inline void bitmap_clear(uint32_t bit) {
+ g_kva_bitmap[bit >> 3] &= ~(1 << (bit & 7));
+}
+
+static inline int bitmap_test(uint32_t bit) {
+ return (g_kva_bitmap[bit >> 3] >> (bit & 7)) & 1;
+}
+
+uintptr_t kva_alloc_pages(uint32_t page_count) {
+ if (page_count == 0 || page_count > KVA_ALLOC_PAGES) {
+ return 0;
+ }
+
+ spin_lock(&g_kva_lock);
+
+ /* Find contiguous free range */
+ uint32_t start = 0;
+ uint32_t found = 0;
+ for (uint32_t i = 0; i <= KVA_ALLOC_PAGES - page_count; i++) {
+ int free = 1;
+ for (uint32_t j = 0; j < page_count; j++) {
+ if (bitmap_test(i + j)) {
+ free = 0;
+ break;
+ }
+ }
+ if (free) {
+ start = i;
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ spin_unlock(&g_kva_lock);
+ return 0;
+ }
+
+ /* Mark pages as allocated */
+ for (uint32_t i = 0; i < page_count; i++) {
+ bitmap_set(start + i);
+ }
+
+ spin_unlock(&g_kva_lock);
+
+ return KVA_ALLOC_BASE + (start << 12);
+}
+
+void kva_free_pages(uintptr_t virt, uint32_t page_count) {
+ if (virt < KVA_ALLOC_BASE || virt >= KVA_ALLOC_END) {
+ return;
+ }
+
+ uint32_t start = (virt - KVA_ALLOC_BASE) >> 12;
+ if (start + page_count > KVA_ALLOC_PAGES) {
+ return;
+ }
+
+ spin_lock(&g_kva_lock);
+
+ for (uint32_t i = 0; i < page_count; i++) {
+ bitmap_clear(start + i);
+ }
+
+ spin_unlock(&g_kva_lock);
+}
#include "shm.h"
#include "net.h"
#include "csprng.h"
+#include "kva_alloc.h"
/* Check if the compiler thinks we are targeting the wrong operating system. */
// 4. Initialize Kernel Heap
kheap_init();
- // 4b. Initialize CSPRNG (M8: real entropy source)
+ // 4b. Initialize KVA allocator (H6: remove fixed VAs)
+ kva_alloc_init();
+
+ // 4c. Initialize CSPRNG (M8: real entropy source)
csprng_init();
// 5. Initialize Shared Memory IPC