fix(kernel): Fix PMM memory page table reservation, ATA driver timeout loops, and PCI probe order

- Fix PMM memory map parsing: always reserve lower 8MB on x86_64 to protect bootloader, GDT, IDT, and PML4 page tables
- Fix ATA driver: add bounded timeouts to ata_wait_ready() and ata_wait_drq() to eliminate infinite busy loops
- Fix PCI bus initialization order: probe PCI devices before AHCI/NVMe/NIC storage and network drivers
- Implement missing pmm_get_total_pages() and pmm_get_usable_memory() getters
This commit is contained in:
subhobhai943 committed 2026-08-18 12:00:33 +05:30
1 parent c02920d11b
commit f5dbc1453c
4 files changed
+138 -81

No files matched your search

+93 -57
View File
@@ -22,32 +22,34 @@ void pmm_init(void* memory_map, uint64_t memory_map_count) {
e820_entry_t* entries = (e820_entry_t*)memory_map;
for (uint64_t i = 0; i < memory_map_count; i++) {
uint64_t base = entries[i].base;
uint64_t length = entries[i].length;
uint32_t type = entries[i].type;
if (memory_map && memory_map_count > 0) {
for (uint64_t i = 0; i < memory_map_count; i++) {
uint64_t base = entries[i].base;
uint64_t length = entries[i].length;
uint32_t type = entries[i].type;
total_memory_bytes += length;
total_memory_bytes += length;
if (type == E820_TYPE_USABLE) {
usable_memory_bytes += length;
if (type == E820_TYPE_USABLE) {
usable_memory_bytes += length;
uint64_t start_page = base / PMM_PAGE_SIZE;
uint64_t page_count = length / PMM_PAGE_SIZE;
uint64_t start_page = base / PMM_PAGE_SIZE;
uint64_t page_count = length / PMM_PAGE_SIZE;
for (uint64_t p = 0; p < page_count; p++) {
uint64_t page = start_page + p;
if (page < MAX_PHYSICAL_PAGES) {
bitmap_clear(page_bitmap, page);
if (page >= total_pages) {
total_pages = page + 1;
for (uint64_t p = 0; p < page_count; p++) {
uint64_t page = start_page + p;
if (page < MAX_PHYSICAL_PAGES) {
bitmap_clear(page_bitmap, page);
if (page >= total_pages) {
total_pages = page + 1;
}
}
}
}
}
}
// Fallback if no E820 usable regions
// Fallback if no E820 usable regions detected
if (usable_memory_bytes == 0 || total_pages == 0) {
#if defined(__aarch64__) || defined(__arm__) || defined(__armv8i__)
uint64_t dram_start = 0x40000000;
@@ -62,11 +64,6 @@ void pmm_init(void* memory_map, uint64_t memory_map_count) {
for (uint64_t p = 0; p < count_pages; p++) {
bitmap_clear(page_bitmap, start_page + p);
}
// Reserve kernel & boot area (0x40000000 - 0x40800000: 8MB / 2048 pages)
for (uint64_t p = start_page; p < start_page + 2048; p++) {
bitmap_set(page_bitmap, p);
}
#else
total_pages = 32768; // 128 MB
total_memory_bytes = 128ULL * 1024 * 1024;
@@ -74,15 +71,23 @@ void pmm_init(void* memory_map, uint64_t memory_map_count) {
for (uint64_t p = 0; p < total_pages; p++) {
bitmap_clear(page_bitmap, p);
}
// Reserve lower 4 MB (bootloader, page tables, kernel image)
size_t kernel_reserved_pages = (4 * 1024 * 1024) / PMM_PAGE_SIZE; // 1024 pages
for (size_t p = 0; p < kernel_reserved_pages; p++) {
bitmap_set(page_bitmap, p);
}
#endif
}
// ALWAYS Reserve Kernel & Critical Bootloader/Page Tables Area
#if defined(__aarch64__) || defined(__arm__) || defined(__armv8i__)
uint64_t dram_start_page = 0x40000000 / PMM_PAGE_SIZE;
for (uint64_t p = dram_start_page; p < dram_start_page + 2048; p++) {
bitmap_set(page_bitmap, p);
}
#else
// Reserve lower 8 MB on x86_64 (IVT, BDA, bootloader, GDT/IDT, PML4 page tables, kernel binary)
size_t kernel_reserved_pages = (8 * 1024 * 1024) / PMM_PAGE_SIZE; // 2048 pages (8MB)
for (size_t p = 0; p < kernel_reserved_pages; p++) {
bitmap_set(page_bitmap, p);
}
#endif
// Count actual used pages (bits set in bitmap up to total_pages)
used_pages = 0;
for (uint64_t p = 0; p < total_pages; p++) {
@@ -98,51 +103,82 @@ void pmm_init(void* memory_map, uint64_t memory_map_count) {
}
void* pmm_alloc_page(void) {
int64_t page = bitmap_find_first_free(page_bitmap, total_pages);
if (page < 0) {
return NULL; // Out of memory
for (uint64_t i = 0; i < total_pages; i++) {
if (!bitmap_test(page_bitmap, i)) {
bitmap_set(page_bitmap, i);
used_pages++;
return (void*)(i * PMM_PAGE_SIZE);
}
}
bitmap_set(page_bitmap, (size_t)page);
used_pages++;
return (void*)(page * PMM_PAGE_SIZE);
return NULL; // Out of memory
}
void* pmm_alloc_pages(size_t count) {
if (count == 0) return NULL;
if (count == 1) return pmm_alloc_page();
int64_t start_page = bitmap_find_contiguous_free(page_bitmap, total_pages, count);
if (start_page < 0) return NULL;
uint64_t consecutive_free = 0;
uint64_t start_page = 0;
for (size_t i = 0; i < count; i++) {
bitmap_set(page_bitmap, (size_t)(start_page + i));
for (uint64_t i = 0; i < total_pages; i++) {
if (!bitmap_test(page_bitmap, i)) {
if (consecutive_free == 0) {
start_page = i;
}
consecutive_free++;
if (consecutive_free == count) {
// Found contiguous block, mark all as allocated
for (uint64_t p = start_page; p < start_page + count; p++) {
bitmap_set(page_bitmap, p);
}
used_pages += count;
return (void*)(start_page * PMM_PAGE_SIZE);
}
} else {
consecutive_free = 0;
}
}
used_pages += count;
return (void*)(start_page * PMM_PAGE_SIZE);
return NULL; // Out of memory for contiguous block
}
void pmm_free_page(void* page) {
uint64_t page_idx = (uint64_t)page / PMM_PAGE_SIZE;
if (page_idx < total_pages && bitmap_test(page_bitmap, page_idx)) {
bitmap_clear(page_bitmap, page_idx);
used_pages--;
void pmm_free_page(void* ptr) {
if (!ptr) return;
uint64_t page = (uint64_t)ptr / PMM_PAGE_SIZE;
if (page < total_pages && bitmap_test(page_bitmap, page)) {
bitmap_clear(page_bitmap, page);
if (used_pages > 0) used_pages--;
}
}
void pmm_free_pages(void* page, size_t count) {
uint64_t start_idx = (uint64_t)page / PMM_PAGE_SIZE;
void pmm_free_pages(void* ptr, size_t count) {
if (!ptr || count == 0) return;
uint64_t start_page = (uint64_t)ptr / PMM_PAGE_SIZE;
for (size_t i = 0; i < count; i++) {
uint64_t page_idx = start_idx + i;
if (page_idx < total_pages && bitmap_test(page_bitmap, page_idx)) {
bitmap_clear(page_bitmap, page_idx);
used_pages--;
uint64_t page = start_page + i;
if (page < total_pages && bitmap_test(page_bitmap, page)) {
bitmap_clear(page_bitmap, page);
if (used_pages > 0) used_pages--;
}
}
}
uint64_t pmm_get_total_pages(void) { return total_pages; }
uint64_t pmm_get_used_pages(void) { return used_pages; }
uint64_t pmm_get_free_pages(void) { return (total_pages > used_pages) ? (total_pages - used_pages) : 0; }
uint64_t pmm_get_total_memory(void) { return total_memory_bytes; }
uint64_t pmm_get_usable_memory(void) { return usable_memory_bytes; }
uint64_t pmm_get_total_memory(void) {
return total_memory_bytes;
}
uint64_t pmm_get_usable_memory(void) {
return usable_memory_bytes;
}
uint64_t pmm_get_total_pages(void) {
return total_pages;
}
uint64_t pmm_get_free_pages(void) {
return (total_pages > used_pages) ? (total_pages - used_pages) : 0;
}
uint64_t pmm_get_used_pages(void) {
return used_pages;
}