Fix PMM: switch to Multiboot2 boot protocol and add documentation (AI)

- Changed grub.cfg from 'multiboot' to 'multiboot2' command. The PMM parses
  Multiboot2 tag structures, but GRUB was booting with Multiboot1 protocol,
  causing the memory map parsing to silently fail (all memory stayed marked
  as used, leading to OOM on every allocation).
- Fixed BITMAP_SIZE calculation to properly round up instead of truncating,
  ensuring the last few pages of the address space are covered.
- Fixed sign comparison warning in bitmap init loop.
- Added debug output to PMM init (mem_upper, region count) for diagnostics.
- Removed stale Multiboot1 magic constant and (void)addr cast from kernel.c.
- Added documentation for the interrupt subsystem and PMM in docs/.
- Checked off 'Implement a PIC handler' and 'Create a physical memory
  allocator' in the task list.

Tested: kernel boots in QEMU with both 4MB and 128MB RAM, PMM correctly
allocates from NORMAL zone (0x01000000) and DMA zone (0x00001000).
This commit is contained in:
AI
2026-02-23 10:57:56 +00:00
parent cf3059747a
commit f2e7d6c5d7
6 changed files with 147 additions and 11 deletions

View File

@@ -15,8 +15,6 @@ void offset_print(const char *str)
}
}
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
void print_hex(uint32_t val)
{
const char *hex = "0123456789ABCDEF";
@@ -29,9 +27,7 @@ void print_hex(uint32_t val)
}
void kernel_main(uint32_t magic, uint32_t addr) {
(void)addr; // Unused for now
if (magic != MULTIBOOT2_BOOTLOADER_MAGIC && magic != MULTIBOOT_BOOTLOADER_MAGIC) {
if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
offset_print("Invalid magic number: ");
print_hex(magic);
return;

View File

@@ -1,12 +1,18 @@
#include "pmm.h"
#include "port_io.h"
#include <multiboot2.h>
extern uint32_t _kernel_start;
extern uint32_t _kernel_end;
/* Printing helpers (defined in kernel.c) */
extern void offset_print(const char *str);
extern void print_hex(uint32_t val);
#define MAX_PHYSICAL_MEMORY 0xFFFFFFFF // 4GB
#define BITMAP_SIZE (MAX_PHYSICAL_MEMORY / PAGE_SIZE / 32)
#define TOTAL_FRAMES (MAX_PHYSICAL_MEMORY / PAGE_SIZE + 1)
#define FRAMES_PER_INDEX 32
#define BITMAP_SIZE ((TOTAL_FRAMES + FRAMES_PER_INDEX - 1) / FRAMES_PER_INDEX)
static uint32_t memory_bitmap[BITMAP_SIZE];
static uint32_t memory_size = 0;
@@ -42,17 +48,18 @@ void init_pmm(uint32_t multiboot_addr) {
uint32_t addr = multiboot_addr;
/* Initialize all memory as used (1) initially */
for (int i = 0; i < BITMAP_SIZE; i++) {
for (uint32_t i = 0; i < BITMAP_SIZE; i++) {
memory_bitmap[i] = 0xFFFFFFFF;
}
if (addr & 7) {
// offset_print("Multiboot alignment error\n"); // Need offset_print here? No, kernel handles prints
offset_print(" PMM: multiboot alignment error\n");
return; // Alignment issue
}
uint32_t size = *(uint32_t *)addr;
uint32_t regions_found = 0;
for (tag = (struct multiboot_tag *)(addr + 8);
tag->type != MULTIBOOT_TAG_TYPE_END;
tag = (struct multiboot_tag *)((multiboot_uint8_t *)tag + ((tag->size + 7) & ~7))) {
@@ -60,6 +67,8 @@ void init_pmm(uint32_t multiboot_addr) {
if (tag->type == MULTIBOOT_TAG_TYPE_BASIC_MEMINFO) {
struct multiboot_tag_basic_meminfo *meminfo = (struct multiboot_tag_basic_meminfo *)tag;
memory_size = meminfo->mem_upper;
offset_print(" PMM: mem_upper = ");
print_hex(memory_size);
} else if (tag->type == MULTIBOOT_TAG_TYPE_MMAP) {
multiboot_memory_map_t *mmap;
struct multiboot_tag_mmap *tag_mmap = (struct multiboot_tag_mmap *)tag;
@@ -73,6 +82,8 @@ void init_pmm(uint32_t multiboot_addr) {
uint64_t len = mmap->len;
uint64_t end = start + len;
regions_found++;
if (start % PAGE_SIZE != 0) {
start = (start + PAGE_SIZE) & ~(PAGE_SIZE - 1);
}
@@ -109,6 +120,10 @@ void init_pmm(uint32_t multiboot_addr) {
// Mark first page as used to avoid returning 0 (NULL)
set_frame(0);
offset_print(" PMM: found ");
print_hex(regions_found);
offset_print(" PMM: available memory regions\n");
}
phys_addr_t pmm_alloc_page(pmm_zone_t zone) {