1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-28 11:27:36 +00:00

Kernel/riscv64: Take the memory map from the FDT and dump it

For this the BootInfo struct was made architecture specific
This commit is contained in:
Hendiadyoin1 2024-01-26 14:37:36 +01:00 committed by Andrew Kaster
parent 21a21c6a11
commit d3f6b03733
10 changed files with 368 additions and 119 deletions

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2024, Leon Albrecht <leon.a@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Arch/riscv64/CPU.h>
#include <Kernel/Memory/MemoryManager.h>
#include <Userland/Libraries/LibDeviceTree/FlattenedDeviceTree.h>
#include <Userland/Libraries/LibDeviceTree/Validation.h>
namespace Kernel {
BootInfo s_boot_info;
alignas(PAGE_SIZE) __attribute__((section(".bss.fdt"))) u8 s_fdt_storage[fdt_storage_size];
void dump_fdt()
{
auto& header = *bit_cast<DeviceTree::FlattenedDeviceTreeHeader*>(&s_fdt_storage[0]);
auto fdt = ReadonlyBytes(s_fdt_storage, header.totalsize);
MUST(DeviceTree::dump(header, fdt));
}
}

View file

@ -6,5 +6,18 @@
#pragma once
#include <Kernel/Memory/PhysicalAddress.h>
#include <Kernel/Prekernel/Prekernel.h>
#include <AK/Platform.h>
VALIDATE_IS_RISCV64()
namespace Kernel {
constexpr size_t fdt_storage_size = 2 * MiB;
extern u8 s_fdt_storage[fdt_storage_size];
extern BootInfo s_boot_info;
void dump_fdt();
}

View file

@ -6,12 +6,14 @@
#include <AK/Types.h>
#include <Kernel/Arch/riscv64/CPU.h>
#include <Kernel/Arch/riscv64/MMU.h>
#include <Kernel/Arch/riscv64/PageDirectory.h>
#include <Kernel/Arch/riscv64/SBI.h>
#include <Kernel/Arch/riscv64/pre_init.h>
#include <Kernel/Memory/MemoryManager.h>
#include <Kernel/Sections.h>
#include <LibDeviceTree/FlattenedDeviceTree.h>
// These come from the linker script
extern u8 page_tables_phys_start[];
@ -173,10 +175,11 @@ static UNMAP_AFTER_INIT void setup_kernel_page_directory(u64* root_table)
}
// This function has to fit into one page as it will be identity mapped.
[[gnu::aligned(PAGE_SIZE)]] [[noreturn]] UNMAP_AFTER_INIT static void enable_paging(FlatPtr satp, u64* enable_paging_pte)
[[gnu::aligned(PAGE_SIZE)]] [[noreturn]] UNMAP_AFTER_INIT static void enable_paging(BootInfo const& info, FlatPtr satp, u64* enable_paging_pte)
{
// Switch current root page table to argument 0. This will immediately take effect, but we won't not crash as this function is identity mapped.
// Also, set up a temporary trap handler to catch any traps while switching page tables.
register FlatPtr a0 asm("a0") = bit_cast<FlatPtr>(&info);
asm volatile(
" lla t0, 1f \n"
" csrw stvec, t0 \n"
@ -210,21 +213,33 @@ static UNMAP_AFTER_INIT void setup_kernel_page_directory(u64* root_table)
" wfi \n"
" j 1b \n"
:
: [satp] "r"(satp), [offset] "r"(calculate_physical_to_link_time_address_offset()), [enable_paging_pte] "r"(enable_paging_pte)
: "r"(a0), [satp] "r"(satp), [offset] "r"(calculate_physical_to_link_time_address_offset()), [enable_paging_pte] "r"(enable_paging_pte)
: "t0");
VERIFY_NOT_REACHED();
}
[[noreturn]] UNMAP_AFTER_INIT void init_page_tables_and_jump_to_init()
[[noreturn]] UNMAP_AFTER_INIT void init_page_tables_and_jump_to_init(FlatPtr mhartid, PhysicalPtr fdt_phys_addr)
{
if (RISCV64::CSR::SATP::read().MODE != RISCV64::CSR::SATP::Mode::Bare)
panic_without_mmu("Kernel booted with MMU enabled"sv);
// Copy the FDT to a known location
DeviceTree::FlattenedDeviceTreeHeader* fdt_header = bit_cast<DeviceTree::FlattenedDeviceTreeHeader*>(fdt_phys_addr);
u8* fdt_storage = bit_cast<u8*>(fdt_phys_addr);
if (fdt_header->totalsize > fdt_storage_size)
panic_without_mmu("Passed FDT is bigger than the internal storage"sv);
for (size_t o = 0; o < fdt_header->totalsize; o += 1) {
// FIXME: Maybe increase the IO size here
adjust_by_mapping_base(s_fdt_storage)[o] = fdt_storage[o];
}
*adjust_by_mapping_base(&physical_to_virtual_offset) = calculate_physical_to_link_time_address_offset();
*adjust_by_mapping_base(&kernel_mapping_base) = KERNEL_MAPPING_BASE;
*adjust_by_mapping_base(&kernel_load_base) = KERNEL_MAPPING_BASE;
*adjust_by_mapping_base(&s_boot_info) = { .mhartid = mhartid, .fdt_phys_addr = fdt_phys_addr };
PageBumpAllocator allocator(adjust_by_mapping_base(reinterpret_cast<u64*>(page_tables_phys_start)), adjust_by_mapping_base(reinterpret_cast<u64*>(page_tables_phys_end)));
auto* root_table = allocator.take_page();
build_mappings(allocator, root_table);
@ -247,7 +262,7 @@ static UNMAP_AFTER_INIT void setup_kernel_page_directory(u64* root_table)
.MODE = RISCV64::CSR::SATP::Mode::Sv39,
};
enable_paging(bit_cast<FlatPtr>(satp), &enable_paging_level0_table[enable_paging_vpn_0]);
enable_paging(s_boot_info, bit_cast<FlatPtr>(satp), &enable_paging_level0_table[enable_paging_vpn_0]);
}
}

View file

@ -7,12 +7,13 @@
#pragma once
#include <AK/Forward.h>
#include <Kernel/Prekernel/Prekernel.h>
#include <AK/Platform.h>
VALIDATE_IS_RISCV64()
namespace Kernel::Memory {
[[noreturn]] void init_page_tables_and_jump_to_init();
[[noreturn]] void init_page_tables_and_jump_to_init(FlatPtr mhartid, PhysicalPtr fdt_phys_addr);
}

View file

@ -45,13 +45,11 @@ UNMAP_AFTER_INIT void dbgln_without_mmu(StringView message)
extern "C" [[noreturn]] UNMAP_AFTER_INIT void pre_init(FlatPtr mhartid, PhysicalPtr fdt_phys_addr)
{
(void)mhartid;
(void)fdt_phys_addr;
// Catch traps in pre_init
RISCV64::CSR::write(RISCV64::CSR::Address::STVEC, bit_cast<FlatPtr>(&early_trap_handler));
Memory::init_page_tables_and_jump_to_init();
Memory::init_page_tables_and_jump_to_init(mhartid, fdt_phys_addr);
}
}