Kernel: Add better support for bootloaders loading the kernel

Before I assumed that bootloaders loaded the kernel at physical address
0, but this patch kinda allows loading to different addresses. This
still doesn't fully work as kernel bootstrap paging relies on kernel
being loaded at 0
This commit is contained in:
Bananymous 2024-08-22 14:20:51 +03:00
parent abc788c756
commit fb35f06cf5
10 changed files with 40 additions and 12 deletions

View File

@ -172,3 +172,5 @@ banan_boot_info:
.long framebuffer .long framebuffer
boot_memory_map: boot_memory_map:
.long memory_map .long memory_map
boot_kernel_paddr:
.long 0

View File

@ -1,3 +1,4 @@
#include <kernel/BootInfo.h>
#include <kernel/CPUID.h> #include <kernel/CPUID.h>
#include <kernel/Lock/SpinLock.h> #include <kernel/Lock/SpinLock.h>
#include <kernel/Memory/kmalloc.h> #include <kernel/Memory/kmalloc.h>
@ -128,6 +129,18 @@ namespace Kernel
return (uint64_t*)page; return (uint64_t*)page;
} }
template<typename T>
static paddr_t V2P(const T vaddr)
{
return (vaddr_t)vaddr - KERNEL_OFFSET + g_boot_info.kernel_paddr;
}
template<typename T>
static vaddr_t P2V(const T paddr)
{
return (paddr_t)paddr - g_boot_info.kernel_paddr + KERNEL_OFFSET;
}
void PageTable::initialize_kernel() void PageTable::initialize_kernel()
{ {
ASSERT(s_global_pdpte == 0); ASSERT(s_global_pdpte == 0);

View File

@ -1,6 +1,5 @@
#include <kernel/Arch.h> #include <kernel/BootInfo.h>
#include <kernel/CPUID.h> #include <kernel/CPUID.h>
#include <kernel/InterruptController.h>
#include <kernel/Lock/SpinLock.h> #include <kernel/Lock/SpinLock.h>
#include <kernel/Memory/kmalloc.h> #include <kernel/Memory/kmalloc.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
@ -147,6 +146,18 @@ namespace Kernel
return (uint64_t*)page; return (uint64_t*)page;
} }
template<typename T>
static paddr_t V2P(const T vaddr)
{
return (vaddr_t)vaddr - KERNEL_OFFSET + g_boot_info.kernel_paddr;
}
template<typename T>
static vaddr_t P2V(const T paddr)
{
return (paddr_t)paddr - g_boot_info.kernel_paddr + KERNEL_OFFSET;
}
void PageTable::initialize_kernel() void PageTable::initialize_kernel()
{ {
ASSERT(s_global_pml4e == 0); ASSERT(s_global_pml4e == 0);

View File

@ -33,4 +33,5 @@ struct BananBootloaderInfo
uint32_t command_line_addr; uint32_t command_line_addr;
uint32_t framebuffer_addr; uint32_t framebuffer_addr;
uint32_t memory_map_addr; uint32_t memory_map_addr;
uint32_t kernel_paddr;
} __attribute__((packed)); } __attribute__((packed));

View File

@ -37,6 +37,7 @@ namespace Kernel
BAN::String command_line; BAN::String command_line;
FramebufferInfo framebuffer {}; FramebufferInfo framebuffer {};
RSDP rsdp {}; RSDP rsdp {};
paddr_t kernel_paddr {};
BAN::Vector<MemoryMapEntry> memory_map_entries; BAN::Vector<MemoryMapEntry> memory_map_entries;
}; };

View File

@ -10,9 +10,6 @@
#error #error
#endif #endif
#define V2P(vaddr) (((vaddr_t)(vaddr)) - KERNEL_OFFSET)
#define P2V(paddr) (((paddr_t)(paddr)) + KERNEL_OFFSET)
#define PAGE_SIZE ((uintptr_t)4096) #define PAGE_SIZE ((uintptr_t)4096)
#define PAGE_SIZE_SHIFT 12 #define PAGE_SIZE_SHIFT 12
#define PAGE_ADDR_MASK (~(uintptr_t)0xFFF) #define PAGE_ADDR_MASK (~(uintptr_t)0xFFF)

View File

@ -254,7 +254,7 @@ acpi_release_global_lock:
return *s_instance; return *s_instance;
} }
static bool is_rsdp(uintptr_t rsdp_addr) static bool is_rsdp(vaddr_t rsdp_addr)
{ {
const RSDP* rsdp = (const RSDP*)rsdp_addr; const RSDP* rsdp = (const RSDP*)rsdp_addr;
@ -287,7 +287,7 @@ acpi_release_global_lock:
return &g_boot_info.rsdp; return &g_boot_info.rsdp;
// Look in main BIOS area below 1 MB // Look in main BIOS area below 1 MB
for (uintptr_t addr = P2V(0x000E0000); addr < P2V(0x000FFFFF); addr += 16) for (vaddr_t addr = 0x000E0000 + KERNEL_OFFSET; addr < 0x000FFFFF + KERNEL_OFFSET; addr += 16)
if (is_rsdp(addr)) if (is_rsdp(addr))
return reinterpret_cast<const RSDP*>(addr); return reinterpret_cast<const RSDP*>(addr);
return nullptr; return nullptr;

View File

@ -66,6 +66,8 @@ namespace Kernel
memcpy(&g_boot_info.rsdp, &rsdp, BAN::Math::min<uint32_t>(rsdp.length, sizeof(g_boot_info.rsdp))); memcpy(&g_boot_info.rsdp, &rsdp, BAN::Math::min<uint32_t>(rsdp.length, sizeof(g_boot_info.rsdp)));
} }
} }
g_boot_info.kernel_paddr = 0;
} }
static BAN::StringView get_early_boot_command_line_multiboot2(uint32_t info) static BAN::StringView get_early_boot_command_line_multiboot2(uint32_t info)
@ -104,6 +106,8 @@ namespace Kernel
g_boot_info.memory_map_entries[i].length = mmap_entry.length; g_boot_info.memory_map_entries[i].length = mmap_entry.length;
g_boot_info.memory_map_entries[i].type = mmap_entry.type; g_boot_info.memory_map_entries[i].type = mmap_entry.type;
} }
g_boot_info.kernel_paddr = banan_bootloader_info.kernel_paddr;
} }
static BAN::StringView get_early_boot_command_line_banan_bootloader(uint32_t info) static BAN::StringView get_early_boot_command_line_banan_bootloader(uint32_t info)

View File

@ -40,8 +40,8 @@ namespace Kernel
continue; continue;
paddr_t start = entry.address; paddr_t start = entry.address;
if (start < V2P(g_kernel_end)) if (start < (vaddr_t)g_kernel_end - KERNEL_OFFSET + g_boot_info.kernel_paddr)
start = V2P(g_kernel_end); start = (vaddr_t)g_kernel_end - KERNEL_OFFSET + g_boot_info.kernel_paddr;
if (auto rem = start % PAGE_SIZE) if (auto rem = start % PAGE_SIZE)
start += PAGE_SIZE - rem; start += PAGE_SIZE - rem;

View File

@ -1,9 +1,8 @@
#include <BAN/Errors.h> #include <BAN/Errors.h>
#include <kernel/kprint.h> #include <kernel/kprint.h>
#include <kernel/BootInfo.h>
#include <kernel/Memory/kmalloc.h> #include <kernel/Memory/kmalloc.h>
#include <kernel/Thread.h>
#define MB (1 << 20) #define MB (1 << 20)
extern uint8_t g_kernel_end[]; extern uint8_t g_kernel_end[];
@ -424,7 +423,7 @@ BAN::Optional<Kernel::paddr_t> kmalloc_paddr_of(Kernel::vaddr_t vaddr)
using namespace Kernel; using namespace Kernel;
if ((vaddr_t)s_kmalloc_storage <= vaddr && vaddr < (vaddr_t)s_kmalloc_storage + sizeof(s_kmalloc_storage)) if ((vaddr_t)s_kmalloc_storage <= vaddr && vaddr < (vaddr_t)s_kmalloc_storage + sizeof(s_kmalloc_storage))
return V2P(vaddr); return vaddr - KERNEL_OFFSET + g_boot_info.kernel_paddr;
return {}; return {};
} }