From f5dbc1453c111153e8739f09a71a14dcbe15b058 Mon Sep 17 00:00:00 2001 From: subhobhai943 Date: Tue, 18 Aug 2026 12:00:33 +0530 Subject: [PATCH] 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 --- drivers/block/ata.c | 60 +++++++++------ include/config/autoconf.h | 4 +- kernel/main.c | 5 +- mm/pmm.c | 150 +++++++++++++++++++++++--------------- 4 files changed, 138 insertions(+), 81 deletions(-) diff --git a/drivers/block/ata.c b/drivers/block/ata.c index cd15a0d..5b574ff 100644 --- a/drivers/block/ata.c +++ b/drivers/block/ata.c @@ -5,18 +5,31 @@ static ata_device_t primary_master; -static void ata_wait_ready(uint16_t io_base) { +static bool ata_wait_ready(uint16_t io_base) { // 400ns delay - inb(io_base + 7); - inb(io_base + 7); - inb(io_base + 7); - inb(io_base + 7); + for (int i = 0; i < 4; i++) { + inb(io_base + 7); + } - while (inb(io_base + 7) & 0x80); // Wait while BSY (Busy) bit is set + for (uint32_t timeout = 50000; timeout > 0; timeout--) { + if (!(inb(io_base + 7) & 0x80)) { + return true; // BSY bit cleared + } + } + return false; } -static void ata_wait_drq(uint16_t io_base) { - while (!(inb(io_base + 7) & 0x08)); // Wait while DRQ (Data Request) bit is clear +static bool ata_wait_drq(uint16_t io_base) { + for (uint32_t timeout = 50000; timeout > 0; timeout--) { + uint8_t status = inb(io_base + 7); + if (status & 0x08) { + return true; // DRQ bit set + } + if (status & 0x01) { + return false; // ERR bit set + } + } + return false; } bool ata_init(void) { @@ -35,7 +48,9 @@ bool ata_init(void) { return false; // No drive } - ata_wait_ready(ATA_PRIMARY_IO); + if (!ata_wait_ready(ATA_PRIMARY_IO)) { + return false; + } uint8_t mid = inb(ATA_PRIMARY_IO + 4); uint8_t hi = inb(ATA_PRIMARY_IO + 5); @@ -43,7 +58,9 @@ bool ata_init(void) { return false; // ATAPI or not ATA } - ata_wait_drq(ATA_PRIMARY_IO); + if (!ata_wait_drq(ATA_PRIMARY_IO)) { + return false; + } uint16_t identify_data[256]; for (int i = 0; i < 256; i++) { @@ -77,7 +94,7 @@ bool ata_init(void) { bool ata_read_sectors(uint32_t lba, uint8_t count, void* buffer) { if (!primary_master.present || !buffer || count == 0) return false; - ata_wait_ready(ATA_PRIMARY_IO); + if (!ata_wait_ready(ATA_PRIMARY_IO)) return false; outb(ATA_PRIMARY_IO + 6, 0xE0 | ((lba >> 24) & 0x0F)); // Master, LBA mode outb(ATA_PRIMARY_IO + 2, count); @@ -89,8 +106,9 @@ bool ata_read_sectors(uint32_t lba, uint8_t count, void* buffer) { uint16_t* ptr = (uint16_t*)buffer; for (uint8_t s = 0; s < count; s++) { - ata_wait_ready(ATA_PRIMARY_IO); - ata_wait_drq(ATA_PRIMARY_IO); + if (!ata_wait_ready(ATA_PRIMARY_IO) || !ata_wait_drq(ATA_PRIMARY_IO)) { + return false; + } for (int i = 0; i < 256; i++) { *ptr++ = inw(ATA_PRIMARY_IO); @@ -103,7 +121,7 @@ bool ata_read_sectors(uint32_t lba, uint8_t count, void* buffer) { bool ata_write_sectors(uint32_t lba, uint8_t count, const void* buffer) { if (!primary_master.present || !buffer || count == 0) return false; - ata_wait_ready(ATA_PRIMARY_IO); + if (!ata_wait_ready(ATA_PRIMARY_IO)) return false; outb(ATA_PRIMARY_IO + 6, 0xE0 | ((lba >> 24) & 0x0F)); outb(ATA_PRIMARY_IO + 2, count); @@ -115,21 +133,21 @@ bool ata_write_sectors(uint32_t lba, uint8_t count, const void* buffer) { const uint16_t* ptr = (const uint16_t*)buffer; for (uint8_t s = 0; s < count; s++) { - ata_wait_ready(ATA_PRIMARY_IO); - ata_wait_drq(ATA_PRIMARY_IO); + if (!ata_wait_ready(ATA_PRIMARY_IO) || !ata_wait_drq(ATA_PRIMARY_IO)) { + return false; + } for (int i = 0; i < 256; i++) { outw(ATA_PRIMARY_IO, *ptr++); } - } - // Flush Cache - outb(ATA_PRIMARY_IO + 7, 0xE7); - ata_wait_ready(ATA_PRIMARY_IO); + outb(ATA_PRIMARY_IO + 7, 0xE7); // Cache Flush + if (!ata_wait_ready(ATA_PRIMARY_IO)) return false; + } return true; } const ata_device_t* ata_get_primary_master(void) { - return &primary_master; + return primary_master.present ? &primary_master : NULL; } diff --git a/include/config/autoconf.h b/include/config/autoconf.h index fa3de24..60cb873 100644 --- a/include/config/autoconf.h +++ b/include/config/autoconf.h @@ -2,8 +2,8 @@ #ifndef _AUTOCONF_H #define _AUTOCONF_H -#define CONFIG_ARCH "x86_64" -#define CONFIG_ARCH_X86_64 1 +#define CONFIG_ARCH "armv8i" +#define CONFIG_ARCH_ARMV8I 1 #define CONFIG_BPF_VM 1 #define CONFIG_DRV_AHCI 1 #define CONFIG_DRV_ATA 1 diff --git a/kernel/main.c b/kernel/main.c index 56a8f5a..1a4ab14 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -76,6 +76,10 @@ #include static void subos_modular_core_boot(void) { +#if defined(__x86_64__) + pci_init(); +#endif + // Storage & Block Layer printk(KERN_INFO "[4/14] Initializing Block Layer & Storage Controllers... "); block_init(); @@ -91,7 +95,6 @@ static void subos_modular_core_boot(void) { // Bus & Devices printk(KERN_INFO "[5/14] Enumerating System Devices, Canvas & PTY... "); #if defined(__x86_64__) - pci_init(); virt_init(); fb_init(); bochs_vbe_init(); diff --git a/mm/pmm.c b/mm/pmm.c index 6454fe7..53d80a9 100644 --- a/mm/pmm.c +++ b/mm/pmm.c @@ -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; +} +