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:
@@ -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;
|
||||
|
||||
21
src/pmm.c
21
src/pmm.c
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user