#include <stdint.h>
-static uint64_t align_up_local(uint64_t value, uint64_t align) {
+/* 32-bit x86: we cap usable RAM at MAX_RAM_SIZE (defined in pmm.c). */
+#define PMM_MAX_RAM (512U * 1024U * 1024U)
+
+static uint32_t align_up32(uint32_t value, uint32_t align) {
return (value + align - 1) & ~(align - 1);
}
-static uint64_t align_down_local(uint64_t value, uint64_t align) {
+static uint32_t align_down32(uint32_t value, uint32_t align) {
return value & ~(align - 1);
}
+#define MB2_TAG_NEXT(t) \
+ ((struct multiboot_tag *)((uint8_t *)(t) + (((t)->size + 7U) & ~7U)))
+
void pmm_arch_init(void* boot_info) {
if (!boot_info) {
kprintf("[PMM] Error: boot_info is NULL!\n");
}
struct multiboot_tag *tag;
- (void)*(uint32_t *)boot_info;
- uint64_t highest_addr = 0;
- uint64_t total_memory = 0;
- int saw_mmap = 0;
- uint64_t freed_frames = 0;
+ uint32_t total_mem = 0;
+ uint32_t highest_avail = 0;
+ int saw_mmap = 0;
+ uint32_t freed_frames = 0;
kprintf("[PMM] Parsing Multiboot2 info...\n");
- // First pass: determine total memory size
+ /* --- Pass 1: determine total usable memory size --- */
for (tag = (struct multiboot_tag *)((uint8_t *)boot_info + 8);
- tag->type != MULTIBOOT_TAG_TYPE_END;
- tag = (struct multiboot_tag *)((uint8_t *)tag + ((tag->size + 7) & ~7)))
+ tag->type != MULTIBOOT_TAG_TYPE_END;
+ tag = MB2_TAG_NEXT(tag))
{
if (tag->type == MULTIBOOT_TAG_TYPE_BASIC_MEMINFO) {
- struct multiboot_tag_basic_meminfo *meminfo = (struct multiboot_tag_basic_meminfo *)tag;
- uint64_t mem_kb = meminfo->mem_upper;
- total_memory = (mem_kb * 1024) + (1024*1024);
+ struct multiboot_tag_basic_meminfo *mi =
+ (struct multiboot_tag_basic_meminfo *)tag;
+ total_mem = (mi->mem_upper * 1024U) + (1024U * 1024U);
}
- else if (tag->type == MULTIBOOT_TAG_TYPE_MMAP) {
+ if (tag->type == MULTIBOOT_TAG_TYPE_MMAP) {
saw_mmap = 1;
- struct multiboot_tag_mmap *mmap = (struct multiboot_tag_mmap *)tag;
- struct multiboot_mmap_entry *entry;
-
- for (entry = mmap->entries;
- (uint8_t *)entry < (uint8_t *)mmap + mmap->size;
- entry = (struct multiboot_mmap_entry *)((uint32_t)entry + mmap->entry_size))
+ struct multiboot_tag_mmap *mmap =
+ (struct multiboot_tag_mmap *)tag;
+ struct multiboot_mmap_entry *e;
+ for (e = mmap->entries;
+ (uint8_t *)e < (uint8_t *)mmap + mmap->size;
+ e = (struct multiboot_mmap_entry *)
+ ((uintptr_t)e + mmap->entry_size))
{
- uint64_t end = entry->addr + entry->len;
- if (end > highest_addr) highest_addr = end;
+ if (e->type != MULTIBOOT_MEMORY_AVAILABLE)
+ continue;
+ uint64_t end64 = e->addr + e->len;
+ /* Clamp to 32-bit address space */
+ uint32_t end = (end64 > 0xFFFFFFFFULL)
+ ? 0xFFFFFFFFU : (uint32_t)end64;
+ if (end > highest_avail)
+ highest_avail = end;
}
}
}
- if (highest_addr > total_memory) {
- total_memory = highest_addr;
- }
- if (total_memory == 0) {
- total_memory = 16 * 1024 * 1024;
- }
+ if (highest_avail > total_mem)
+ total_mem = highest_avail;
+ if (total_mem == 0)
+ total_mem = 16U * 1024U * 1024U;
+ if (total_mem > PMM_MAX_RAM)
+ total_mem = PMM_MAX_RAM;
- // pmm_set_limits clamps and configures the bitmap
- pmm_set_limits(total_memory, 0);
+ pmm_set_limits((uint64_t)total_mem, 0);
- // Second pass: free AVAILABLE regions
+ /* --- Pass 2: free AVAILABLE regions --- */
for (tag = (struct multiboot_tag *)((uint8_t *)boot_info + 8);
- tag->type != MULTIBOOT_TAG_TYPE_END;
- tag = (struct multiboot_tag *)((uint8_t *)tag + ((tag->size + 7) & ~7)))
+ tag->type != MULTIBOOT_TAG_TYPE_END;
+ tag = MB2_TAG_NEXT(tag))
{
- if (tag->type == MULTIBOOT_TAG_TYPE_MMAP) {
- struct multiboot_tag_mmap *mmap = (struct multiboot_tag_mmap *)tag;
- struct multiboot_mmap_entry *entry;
+ if (tag->type != MULTIBOOT_TAG_TYPE_MMAP)
+ continue;
+
+ struct multiboot_tag_mmap *mmap =
+ (struct multiboot_tag_mmap *)tag;
+ struct multiboot_mmap_entry *e;
+
+ for (e = mmap->entries;
+ (uint8_t *)e < (uint8_t *)mmap + mmap->size;
+ e = (struct multiboot_mmap_entry *)
+ ((uintptr_t)e + mmap->entry_size))
+ {
+ if (e->type != MULTIBOOT_MEMORY_AVAILABLE)
+ continue;
+
+ uint64_t b64 = e->addr;
+ uint64_t l64 = e->len;
+ if (b64 >= total_mem) continue;
+ if (b64 + l64 > total_mem)
+ l64 = total_mem - b64;
+
+ uint32_t base = align_up32((uint32_t)b64, PAGE_SIZE);
+ uint32_t len = align_down32((uint32_t)l64, PAGE_SIZE);
+ if (len == 0) continue;
- for (entry = mmap->entries;
- (uint8_t *)entry < (uint8_t *)mmap + mmap->size;
- entry = (struct multiboot_mmap_entry *)((uint32_t)entry + mmap->entry_size))
- {
- if (entry->type == MULTIBOOT_MEMORY_AVAILABLE) {
- uint64_t base = entry->addr;
- uint64_t len = entry->len;
-
- if (base >= total_memory) continue;
- if (base + len > total_memory) {
- len = total_memory - base;
- }
- base = align_up_local(base, PAGE_SIZE);
- len = align_down_local(len, PAGE_SIZE);
- if (len == 0) continue;
-
- pmm_mark_region(base, len, 0);
- freed_frames += (len / PAGE_SIZE);
- }
- }
+ pmm_mark_region(base, len, 0);
+ freed_frames += len / PAGE_SIZE;
}
}
- // Fallback if no MMAP tag
+ /* Fallback if no MMAP tag */
if (!saw_mmap) {
- uint64_t base = 0x00100000;
- uint64_t len = (total_memory > base) ? (total_memory - base) : 0;
- base = align_up_local(base, PAGE_SIZE);
- len = align_down_local(len, PAGE_SIZE);
+ uint32_t base = 0x00100000U;
+ uint32_t len = (total_mem > base) ? (total_mem - base) : 0;
+ base = align_up32(base, PAGE_SIZE);
+ len = align_down32(len, PAGE_SIZE);
if (len) {
pmm_mark_region(base, len, 0);
- freed_frames += (len / PAGE_SIZE);
+ freed_frames += len / PAGE_SIZE;
}
}
- // Reserve low memory and frame 0
+ /* Reserve low memory (real-mode IVT, BDA, EBDA, BIOS ROM) */
pmm_mark_region(0, 0x00100000, 1);
- kprintf("[PMM] total_memory bytes: 0x%x\n", (unsigned)total_memory);
- kprintf("[PMM] freed_frames: 0x%x\n", (unsigned)freed_frames);
+ kprintf("[PMM] total_memory: %u bytes (%u MB)\n",
+ total_mem, total_mem / (1024U * 1024U));
+ kprintf("[PMM] freed_frames: %u (%u MB usable)\n",
+ freed_frames, (freed_frames * PAGE_SIZE) / (1024U * 1024U));
if (freed_frames == 0) {
kprintf("[PMM] WARN: no free frames detected (MMAP missing or parse failed).\n");
}
- // Protect Multiboot2 modules (e.g. initrd)
+ /* Protect Multiboot2 modules (e.g. initrd) */
for (tag = (struct multiboot_tag *)((uint8_t *)boot_info + 8);
tag->type != MULTIBOOT_TAG_TYPE_END;
- tag = (struct multiboot_tag *)((uint8_t *)tag + ((tag->size + 7) & ~7)))
+ tag = MB2_TAG_NEXT(tag))
{
if (tag->type == MULTIBOOT_TAG_TYPE_MODULE) {
- struct multiboot_tag_module* mod = (struct multiboot_tag_module*)tag;
- uint64_t mod_start = (uint64_t)mod->mod_start;
- uint64_t mod_end = (uint64_t)mod->mod_end;
- if (mod_end < mod_start) mod_end = mod_start;
-
- uint64_t mod_start_aligned = align_down_local(mod_start, PAGE_SIZE);
- uint64_t mod_end_aligned = align_up_local(mod_end, PAGE_SIZE);
- if (mod_end_aligned < mod_start_aligned) {
- mod_end_aligned = mod_start_aligned;
- }
-
- pmm_mark_region(mod_start_aligned, mod_end_aligned - mod_start_aligned, 1);
+ struct multiboot_tag_module* mod =
+ (struct multiboot_tag_module*)tag;
+ uint32_t ms = align_down32(mod->mod_start, PAGE_SIZE);
+ uint32_t me = align_up32(mod->mod_end, PAGE_SIZE);
+ if (me > ms)
+ pmm_mark_region(ms, me - ms, 1);
}
}
- // Protect Multiboot info structure itself
+ /* Protect Multiboot info structure itself */
uintptr_t kvbase = hal_mm_kernel_virt_base();
uintptr_t bi_ptr = (uintptr_t)boot_info;
if (!kvbase || bi_ptr < kvbase) {