mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-26 00:52:50 +00:00
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:
1 parent
c02920d11b
commit
f5dbc1453c
4 files changed
+117
-60
No files matched your search
+38
-20
@@ -5,18 +5,31 @@
|
|||||||
|
|
||||||
static ata_device_t primary_master;
|
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
|
// 400ns delay
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
inb(io_base + 7);
|
inb(io_base + 7);
|
||||||
inb(io_base + 7);
|
}
|
||||||
inb(io_base + 7);
|
|
||||||
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) {
|
static bool ata_wait_drq(uint16_t io_base) {
|
||||||
while (!(inb(io_base + 7) & 0x08)); // Wait while DRQ (Data Request) bit is clear
|
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) {
|
bool ata_init(void) {
|
||||||
@@ -35,7 +48,9 @@ bool ata_init(void) {
|
|||||||
return false; // No drive
|
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 mid = inb(ATA_PRIMARY_IO + 4);
|
||||||
uint8_t hi = inb(ATA_PRIMARY_IO + 5);
|
uint8_t hi = inb(ATA_PRIMARY_IO + 5);
|
||||||
@@ -43,7 +58,9 @@ bool ata_init(void) {
|
|||||||
return false; // ATAPI or not ATA
|
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];
|
uint16_t identify_data[256];
|
||||||
for (int i = 0; i < 256; i++) {
|
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) {
|
bool ata_read_sectors(uint32_t lba, uint8_t count, void* buffer) {
|
||||||
if (!primary_master.present || !buffer || count == 0) return false;
|
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 + 6, 0xE0 | ((lba >> 24) & 0x0F)); // Master, LBA mode
|
||||||
outb(ATA_PRIMARY_IO + 2, count);
|
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;
|
uint16_t* ptr = (uint16_t*)buffer;
|
||||||
|
|
||||||
for (uint8_t s = 0; s < count; s++) {
|
for (uint8_t s = 0; s < count; s++) {
|
||||||
ata_wait_ready(ATA_PRIMARY_IO);
|
if (!ata_wait_ready(ATA_PRIMARY_IO) || !ata_wait_drq(ATA_PRIMARY_IO)) {
|
||||||
ata_wait_drq(ATA_PRIMARY_IO);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
*ptr++ = inw(ATA_PRIMARY_IO);
|
*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) {
|
bool ata_write_sectors(uint32_t lba, uint8_t count, const void* buffer) {
|
||||||
if (!primary_master.present || !buffer || count == 0) return false;
|
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 + 6, 0xE0 | ((lba >> 24) & 0x0F));
|
||||||
outb(ATA_PRIMARY_IO + 2, count);
|
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;
|
const uint16_t* ptr = (const uint16_t*)buffer;
|
||||||
|
|
||||||
for (uint8_t s = 0; s < count; s++) {
|
for (uint8_t s = 0; s < count; s++) {
|
||||||
ata_wait_ready(ATA_PRIMARY_IO);
|
if (!ata_wait_ready(ATA_PRIMARY_IO) || !ata_wait_drq(ATA_PRIMARY_IO)) {
|
||||||
ata_wait_drq(ATA_PRIMARY_IO);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
outw(ATA_PRIMARY_IO, *ptr++);
|
outw(ATA_PRIMARY_IO, *ptr++);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Flush Cache
|
outb(ATA_PRIMARY_IO + 7, 0xE7); // Cache Flush
|
||||||
outb(ATA_PRIMARY_IO + 7, 0xE7);
|
if (!ata_wait_ready(ATA_PRIMARY_IO)) return false;
|
||||||
ata_wait_ready(ATA_PRIMARY_IO);
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ata_device_t* ata_get_primary_master(void) {
|
const ata_device_t* ata_get_primary_master(void) {
|
||||||
return &primary_master;
|
return primary_master.present ? &primary_master : NULL;
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
#ifndef _AUTOCONF_H
|
#ifndef _AUTOCONF_H
|
||||||
#define _AUTOCONF_H
|
#define _AUTOCONF_H
|
||||||
|
|
||||||
#define CONFIG_ARCH "x86_64"
|
#define CONFIG_ARCH "armv8i"
|
||||||
#define CONFIG_ARCH_X86_64 1
|
#define CONFIG_ARCH_ARMV8I 1
|
||||||
#define CONFIG_BPF_VM 1
|
#define CONFIG_BPF_VM 1
|
||||||
#define CONFIG_DRV_AHCI 1
|
#define CONFIG_DRV_AHCI 1
|
||||||
#define CONFIG_DRV_ATA 1
|
#define CONFIG_DRV_ATA 1
|
||||||
|
|||||||
+4
-1
@@ -76,6 +76,10 @@
|
|||||||
#include <userland/shell.h>
|
#include <userland/shell.h>
|
||||||
|
|
||||||
static void subos_modular_core_boot(void) {
|
static void subos_modular_core_boot(void) {
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
pci_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Storage & Block Layer
|
// Storage & Block Layer
|
||||||
printk(KERN_INFO "[4/14] Initializing Block Layer & Storage Controllers... ");
|
printk(KERN_INFO "[4/14] Initializing Block Layer & Storage Controllers... ");
|
||||||
block_init();
|
block_init();
|
||||||
@@ -91,7 +95,6 @@ static void subos_modular_core_boot(void) {
|
|||||||
// Bus & Devices
|
// Bus & Devices
|
||||||
printk(KERN_INFO "[5/14] Enumerating System Devices, Canvas & PTY... ");
|
printk(KERN_INFO "[5/14] Enumerating System Devices, Canvas & PTY... ");
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
pci_init();
|
|
||||||
virt_init();
|
virt_init();
|
||||||
fb_init();
|
fb_init();
|
||||||
bochs_vbe_init();
|
bochs_vbe_init();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ void pmm_init(void* memory_map, uint64_t memory_map_count) {
|
|||||||
|
|
||||||
e820_entry_t* entries = (e820_entry_t*)memory_map;
|
e820_entry_t* entries = (e820_entry_t*)memory_map;
|
||||||
|
|
||||||
|
if (memory_map && memory_map_count > 0) {
|
||||||
for (uint64_t i = 0; i < memory_map_count; i++) {
|
for (uint64_t i = 0; i < memory_map_count; i++) {
|
||||||
uint64_t base = entries[i].base;
|
uint64_t base = entries[i].base;
|
||||||
uint64_t length = entries[i].length;
|
uint64_t length = entries[i].length;
|
||||||
@@ -46,8 +47,9 @@ void pmm_init(void* memory_map, uint64_t memory_map_count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fallback if no E820 usable regions
|
// Fallback if no E820 usable regions detected
|
||||||
if (usable_memory_bytes == 0 || total_pages == 0) {
|
if (usable_memory_bytes == 0 || total_pages == 0) {
|
||||||
#if defined(__aarch64__) || defined(__arm__) || defined(__armv8i__)
|
#if defined(__aarch64__) || defined(__arm__) || defined(__armv8i__)
|
||||||
uint64_t dram_start = 0x40000000;
|
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++) {
|
for (uint64_t p = 0; p < count_pages; p++) {
|
||||||
bitmap_clear(page_bitmap, start_page + 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
|
#else
|
||||||
total_pages = 32768; // 128 MB
|
total_pages = 32768; // 128 MB
|
||||||
total_memory_bytes = 128ULL * 1024 * 1024;
|
total_memory_bytes = 128ULL * 1024 * 1024;
|
||||||
@@ -74,14 +71,22 @@ void pmm_init(void* memory_map, uint64_t memory_map_count) {
|
|||||||
for (uint64_t p = 0; p < total_pages; p++) {
|
for (uint64_t p = 0; p < total_pages; p++) {
|
||||||
bitmap_clear(page_bitmap, p);
|
bitmap_clear(page_bitmap, p);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Reserve lower 4 MB (bootloader, page tables, kernel image)
|
// ALWAYS Reserve Kernel & Critical Bootloader/Page Tables Area
|
||||||
size_t kernel_reserved_pages = (4 * 1024 * 1024) / PMM_PAGE_SIZE; // 1024 pages
|
#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++) {
|
for (size_t p = 0; p < kernel_reserved_pages; p++) {
|
||||||
bitmap_set(page_bitmap, p);
|
bitmap_set(page_bitmap, p);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
// Count actual used pages (bits set in bitmap up to total_pages)
|
// Count actual used pages (bits set in bitmap up to total_pages)
|
||||||
used_pages = 0;
|
used_pages = 0;
|
||||||
@@ -98,51 +103,82 @@ void pmm_init(void* memory_map, uint64_t memory_map_count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* pmm_alloc_page(void) {
|
void* pmm_alloc_page(void) {
|
||||||
int64_t page = bitmap_find_first_free(page_bitmap, total_pages);
|
for (uint64_t i = 0; i < total_pages; i++) {
|
||||||
if (page < 0) {
|
if (!bitmap_test(page_bitmap, i)) {
|
||||||
return NULL; // Out of memory
|
bitmap_set(page_bitmap, i);
|
||||||
}
|
|
||||||
|
|
||||||
bitmap_set(page_bitmap, (size_t)page);
|
|
||||||
used_pages++;
|
used_pages++;
|
||||||
return (void*)(page * PMM_PAGE_SIZE);
|
return (void*)(i * PMM_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL; // Out of memory
|
||||||
}
|
}
|
||||||
|
|
||||||
void* pmm_alloc_pages(size_t count) {
|
void* pmm_alloc_pages(size_t count) {
|
||||||
if (count == 0) return NULL;
|
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);
|
uint64_t consecutive_free = 0;
|
||||||
if (start_page < 0) return NULL;
|
uint64_t start_page = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (uint64_t i = 0; i < total_pages; i++) {
|
||||||
bitmap_set(page_bitmap, (size_t)(start_page + 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;
|
used_pages += count;
|
||||||
return (void*)(start_page * PMM_PAGE_SIZE);
|
return (void*)(start_page * PMM_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
consecutive_free = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; // Out of memory for contiguous block
|
||||||
}
|
}
|
||||||
|
|
||||||
void pmm_free_page(void* page) {
|
void pmm_free_page(void* ptr) {
|
||||||
uint64_t page_idx = (uint64_t)page / PMM_PAGE_SIZE;
|
if (!ptr) return;
|
||||||
if (page_idx < total_pages && bitmap_test(page_bitmap, page_idx)) {
|
uint64_t page = (uint64_t)ptr / PMM_PAGE_SIZE;
|
||||||
bitmap_clear(page_bitmap, page_idx);
|
if (page < total_pages && bitmap_test(page_bitmap, page)) {
|
||||||
used_pages--;
|
bitmap_clear(page_bitmap, page);
|
||||||
|
if (used_pages > 0) used_pages--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pmm_free_pages(void* page, size_t count) {
|
void pmm_free_pages(void* ptr, size_t count) {
|
||||||
uint64_t start_idx = (uint64_t)page / PMM_PAGE_SIZE;
|
if (!ptr || count == 0) return;
|
||||||
|
uint64_t start_page = (uint64_t)ptr / PMM_PAGE_SIZE;
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
uint64_t page_idx = start_idx + i;
|
uint64_t page = start_page + i;
|
||||||
if (page_idx < total_pages && bitmap_test(page_bitmap, page_idx)) {
|
if (page < total_pages && bitmap_test(page_bitmap, page)) {
|
||||||
bitmap_clear(page_bitmap, page_idx);
|
bitmap_clear(page_bitmap, page);
|
||||||
used_pages--;
|
if (used_pages > 0) used_pages--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t pmm_get_total_pages(void) { return total_pages; }
|
uint64_t pmm_get_total_memory(void) {
|
||||||
uint64_t pmm_get_used_pages(void) { return used_pages; }
|
return total_memory_bytes;
|
||||||
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_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;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user