feat: introduce bootloader-agnostic Boot Contract, add btlist command to list connected Bluetooth devices
This commit is contained in:
@@ -23,7 +23,8 @@ namespace Memory::VMM {
|
||||
PML4 = (PageTable*)SubHHDM((PageTable*)Memory::g_pfa->AllocateZeroed());
|
||||
}
|
||||
|
||||
void Paging::Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize, limine_memmap_response* memMap) {
|
||||
void Paging::Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize, const montauk::boot::MemoryMap& memMap,
|
||||
const montauk::boot::Framebuffer& framebuffer) {
|
||||
// Map kernel
|
||||
Kt::KernelLogStream(Kt::DEBUG, "VMM") << "Paging::Init called with kernelBaseVirt as 0x" << base::hex << kernelBaseVirt;
|
||||
|
||||
@@ -31,15 +32,31 @@ namespace Memory::VMM {
|
||||
Map(GetPhysKernelAddress(pageAddr), pageAddr);
|
||||
}
|
||||
|
||||
// Map HHDM: find the highest physical address and map everything
|
||||
// from 0 to that point. This covers gaps between memory map entries
|
||||
// (e.g. BIOS ROM at 0xE0000) that firmware may not list but the
|
||||
// kernel still needs to access via HHDM.
|
||||
|
||||
// Map HHDM: map physical memory contiguously from 0 up to the top of
|
||||
// real backing store, so the kernel can reach any RAM/firmware byte at
|
||||
// phys+hhdmBase. Mapping from 0 (rather than per-region) also covers
|
||||
// unlisted low gaps -- BIOS ROM at 0xE0000, the EBDA, etc. -- that the
|
||||
// kernel still touches through the HHDM.
|
||||
//
|
||||
// The upper bound is computed over real backing store ONLY: RAM, ACPI
|
||||
// tables, modules, the framebuffer, and so on. Reserved/Unknown
|
||||
// regions are deliberately EXCLUDED from the bound. Firmware commonly
|
||||
// reports the 64-bit PCI MMIO aperture as a Reserved region hundreds of
|
||||
// GiB above RAM (its base scales with the CPU's physical-address width);
|
||||
// letting that inflate maxPhysAddr would make this loop allocate
|
||||
// gigabytes of 4 KiB page tables and exhaust the frame allocator (OOM).
|
||||
// Such MMIO is mapped on demand via MapMMIO with the right cache
|
||||
// attributes -- never through the HHDM -- so it is correct to leave it
|
||||
// out here. Reserved regions that sit *below* the bound (e.g. low BIOS
|
||||
// areas) are still mapped by the contiguous fill.
|
||||
uint64_t maxPhysAddr = 0;
|
||||
for (size_t i = 0; i < memMap->entry_count; i++) {
|
||||
auto entry = memMap->entries[i];
|
||||
uint64_t entryEnd = entry->base + entry->length;
|
||||
for (size_t i = 0; i < memMap.count; i++) {
|
||||
const auto& entry = memMap.regions[i];
|
||||
if (entry.kind == montauk::boot::MemoryKind::Reserved
|
||||
|| entry.kind == montauk::boot::MemoryKind::Unknown) {
|
||||
continue;
|
||||
}
|
||||
uint64_t entryEnd = entry.base + entry.length;
|
||||
if (entryEnd > maxPhysAddr) maxPhysAddr = entryEnd;
|
||||
}
|
||||
maxPhysAddr = (maxPhysAddr + 0xFFF) & ~0xFFFULL;
|
||||
@@ -48,6 +65,24 @@ namespace Memory::VMM {
|
||||
Map(pageAddr, HHDM(pageAddr));
|
||||
}
|
||||
|
||||
// The linear framebuffer can sit in a PCI BAR above the RAM bound we
|
||||
// just mapped (e.g. in the 32-bit MMIO hole), and it is not guaranteed
|
||||
// to appear as a memory-map region. It MUST be reachable through the
|
||||
// HHDM before we switch to these page tables, because the very next log
|
||||
// line (and PAT setup, and Cursor init) renders to it via phys+hhdmBase.
|
||||
// Map its pages explicitly (write-back for now; Cursor upgrades them to
|
||||
// write-combining once PAT is reprogrammed).
|
||||
if (framebuffer.address != 0) {
|
||||
uint64_t fbPhys = Memory::SubHHDM(framebuffer.address);
|
||||
uint64_t fbBytes = framebuffer.height * framebuffer.pitch;
|
||||
uint64_t fbPages = (fbBytes + 0xFFF) / 0x1000;
|
||||
fbPhys &= ~0xFFFULL;
|
||||
for (uint64_t p = 0; p < fbPages; p++) {
|
||||
uint64_t phys = fbPhys + p * 0x1000;
|
||||
Map(phys, HHDM(phys));
|
||||
}
|
||||
}
|
||||
|
||||
LoadCR3(PML4);
|
||||
Kt::KernelLogStream(Kt::OK, "VMM") << "Switched CR3";
|
||||
}
|
||||
@@ -455,12 +490,12 @@ namespace Memory::VMM {
|
||||
return GetPhysAddr((std::uint64_t)PML4, virtualAddress, false);
|
||||
}
|
||||
|
||||
void Paging::MapEfiRuntime(limine_efi_memmap_response* efiMemmap) {
|
||||
if (!efiMemmap) return;
|
||||
void Paging::MapEfiRuntime(const montauk::boot::EfiInfo& efi) {
|
||||
if (efi.memoryMap == nullptr || efi.descriptorSize == 0) return;
|
||||
|
||||
auto* base = (uint8_t*)efiMemmap->memmap;
|
||||
uint64_t descSize = efiMemmap->desc_size;
|
||||
uint64_t count = efiMemmap->memmap_size / descSize;
|
||||
auto* base = (uint8_t*)efi.memoryMap;
|
||||
uint64_t descSize = efi.descriptorSize;
|
||||
uint64_t count = efi.memoryMapSize / descSize;
|
||||
|
||||
struct EfiMemDesc {
|
||||
uint32_t Type;
|
||||
|
||||
Reference in New Issue
Block a user