1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 02:07: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

@ -5,6 +5,7 @@
*/
#include <AK/Types.h>
#include <Kernel/Arch/CPU.h>
#include <Kernel/Arch/InterruptManagement.h>
#include <Kernel/Arch/Processor.h>
#include <Kernel/Boot/BootInfo.h>
@ -217,29 +218,7 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init([[maybe_unused]] BootInfo con
// FIXME: Read the /chosen/bootargs property.
kernel_cmdline = RPi::Mailbox::the().query_kernel_command_line(s_command_line_buffer);
#elif ARCH(RISCV64)
// FIXME: Get the actual memory map from the device tree.
static multiboot_memory_map_t mmap[] = {
{
// We currently can't get the actual size of firmware-reserved memory, so mark the first 0x20'0000 bytes as reserved.
// This reserved memory region should be large enough for now.
sizeof(multiboot_mmap_entry) - sizeof(u32),
0x8000'0000,
0x20'0000,
MULTIBOOT_MEMORY_RESERVED,
},
{
sizeof(multiboot_mmap_entry) - sizeof(u32),
0x8020'0000,
1 * GiB - 0x20'0000,
MULTIBOOT_MEMORY_AVAILABLE,
},
};
multiboot_memory_map = mmap;
multiboot_memory_map_count = array_size(mmap);
multiboot_modules = nullptr;
multiboot_modules_count = 0;
// FIXME: Take this from the flattened device tree (/chosen/bootargs)
kernel_cmdline = "serial_debug"sv;
#endif
@ -308,6 +287,11 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init([[maybe_unused]] BootInfo con
InterruptManagement::initialize();
ACPI::initialize();
#if ARCH(RISCV64)
// FIXME: Unflatten the device tree and use it for device discovery
dump_fdt();
#endif
// Initialize TimeManagement before using randomness!
TimeManagement::initialize(0);

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);
}
}