From cb9398bb1b25f450cde097e02f9d2b3677ce4757 Mon Sep 17 00:00:00 2001 From: Yu Duan Date: Mon, 5 Feb 2024 19:19:09 +0000 Subject: [PATCH] Detect memory from fdt --- Cargo.lock | 4 +-- Cargo.toml | 2 +- src/arch/x86_64/kernel/mod.rs | 7 +++++ src/arch/x86_64/mm/physicalmem.rs | 47 +++++++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0d702d61a..8749bf96b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -523,9 +523,9 @@ checksum = "89e0de208fa9b99664812350b33072d0d9b3a63caaebb03eeb23316eeedfb8d0" [[package]] name = "hermit-entry" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e907e00c48a6a1e1b321654d6cf90d0568ae0e6466646c3da302508cf53dc44e" +checksum = "22ad63cf6566d7a38eba91d21e704730f2c3751c3da2d9c6a71136e00d97097e" dependencies = [ "align-address", "time", diff --git a/Cargo.toml b/Cargo.toml index ba9450661b..c7f391a14a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,6 +75,7 @@ bitflags = "2.4" cfg-if = "1" crossbeam-utils = { version = "0.8", default-features = false } dyn-clone = "1.0" +fdt = "0.1" hashbrown = { version = "0.14", default-features = false } hermit-entry = { version = "0.9", features = ["kernel"] } hermit-sync = "0.1" @@ -132,7 +133,6 @@ hermit-dtb = { version = "0.1" } semihosting = { version = "0.1", optional = true } [target.'cfg(target_arch = "riscv64")'.dependencies] -fdt = "0.1" riscv = "0.11" sbi = "0.2" trapframe = "0.9" diff --git a/src/arch/x86_64/kernel/mod.rs b/src/arch/x86_64/kernel/mod.rs index 5fa19f5fb8..782d2a9ea5 100644 --- a/src/arch/x86_64/kernel/mod.rs +++ b/src/arch/x86_64/kernel/mod.rs @@ -82,6 +82,13 @@ pub fn get_mbinfo() -> VirtAddr { } } +pub fn get_fdt() -> Option { + boot_info() + .hardware_info + .device_tree + .map(|fdt| fdt.get() as usize) +} + #[cfg(feature = "smp")] pub fn get_possible_cpus() -> u32 { use core::cmp; diff --git a/src/arch/x86_64/mm/physicalmem.rs b/src/arch/x86_64/mm/physicalmem.rs index 1b4ef97725..7100b6677a 100644 --- a/src/arch/x86_64/mm/physicalmem.rs +++ b/src/arch/x86_64/mm/physicalmem.rs @@ -5,7 +5,7 @@ use ::x86_64::structures::paging::{FrameAllocator, PhysFrame}; use hermit_sync::InterruptTicketMutex; use multiboot::information::{MemoryType, Multiboot}; -use crate::arch::x86_64::kernel::{get_limit, get_mbinfo}; +use crate::arch::x86_64::kernel::{get_fdt, get_limit, get_mbinfo}; use crate::arch::x86_64::mm::paging::{BasePageSize, PageSize}; use crate::arch::x86_64::mm::{MultibootMemory, PhysAddr, VirtAddr}; use crate::mm; @@ -19,6 +19,48 @@ const KVM_32BIT_MAX_MEM_SIZE: usize = 1 << 32; const KVM_32BIT_GAP_SIZE: usize = 768 << 20; const KVM_32BIT_GAP_START: usize = KVM_32BIT_MAX_MEM_SIZE - KVM_32BIT_GAP_SIZE; +fn detect_from_fdt() -> Result<(), ()> { + let fdt_addr = get_fdt().ok_or(())?; + let fdt = unsafe { fdt::Fdt::from_ptr(fdt_addr as *const u8).unwrap() }; + + let mems = fdt.find_all_nodes("/memory"); + let all_regions = mems.map(|m| m.reg().unwrap().next().unwrap()); + + let mut found_ram = false; + + for m in all_regions { + let start_address = m.starting_address as u64; + let size = m.size.unwrap() as u64; + let end_address = start_address + size; + + if end_address <= mm::kernel_end_address().as_u64() { + continue; + } + + found_ram = true; + + let start_address = if start_address <= mm::kernel_start_address().as_u64() { + mm::kernel_end_address() + } else { + VirtAddr(start_address) + }; + + let entry = FreeListEntry::new(start_address.as_usize(), end_address as usize); + let _ = TOTAL_MEMORY.fetch_add( + (end_address - start_address.as_u64()) as usize, + Ordering::SeqCst, + ); + PHYSICAL_FREE_LIST.lock().push(entry); + } + + assert!( + found_ram, + "Could not find any available RAM in the Devicetree Memory Map" + ); + + Ok(()) +} + fn detect_from_multiboot_info() -> Result<(), ()> { let mb_info = get_mbinfo(); if mb_info.is_zero() { @@ -91,7 +133,8 @@ fn detect_from_limits() -> Result<(), ()> { } pub fn init() { - detect_from_multiboot_info() + detect_from_fdt() + .or_else(|_e| detect_from_multiboot_info()) .or_else(|_e| detect_from_limits()) .unwrap(); }