diff --git a/src/arch/aarch64/kernel/interrupts.rs b/src/arch/aarch64/kernel/interrupts.rs index 0717b2222f..0ab87dbcef 100644 --- a/src/arch/aarch64/kernel/interrupts.rs +++ b/src/arch/aarch64/kernel/interrupts.rs @@ -19,7 +19,7 @@ use crate::arch::aarch64::kernel::scheduler::State; use crate::arch::aarch64::kernel::serial::handle_uart_interrupt; use crate::arch::aarch64::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags}; use crate::drivers::InterruptHandlerMap; -use crate::env; +use crate::env::{self, BootInfoExt}; use crate::mm::{PageAlloc, PageRangeAllocator}; use crate::scheduler::{self, CoreId, timer_interrupts}; @@ -266,7 +266,7 @@ pub fn wakeup_core(core_id: CoreId) { pub(crate) fn init() { info!("Initialize generic interrupt controller"); - let fdt = env::fdt().unwrap(); + let fdt = env::start_info().fdt().unwrap(); let intc_node = fdt.find_node("/intc").unwrap(); let mut reg_iter = intc_node.reg().unwrap(); @@ -445,7 +445,7 @@ pub fn init_cpu() { GicCpuInterface::enable_group1(true); GicCpuInterface::set_priority_mask(0xff); - let fdt = env::fdt().unwrap(); + let fdt = env::start_info().fdt().unwrap(); if let Some(timer_node) = fdt.find_compatible(&["arm,armv8-timer", "arm,armv7-timer"]) { let irq_slice = timer_node.property("interrupts").unwrap().value; diff --git a/src/arch/aarch64/kernel/mmio.rs b/src/arch/aarch64/kernel/mmio.rs index 4c6730ffe8..bc3f59176a 100644 --- a/src/arch/aarch64/kernel/mmio.rs +++ b/src/arch/aarch64/kernel/mmio.rs @@ -36,6 +36,7 @@ use crate::drivers::virtio::transport::mmio as mmio_virtio; use crate::drivers::virtio::transport::mmio::VirtioDriver; #[cfg(feature = "virtio-vsock")] use crate::drivers::vsock::VirtioVsockDriver; +use crate::env::BootInfoExt; #[cfg(feature = "virtio-net")] use crate::executor::device::NETWORK_DEVICE; use crate::init_cell::InitCell; @@ -120,7 +121,7 @@ pub(crate) fn get_vsock_driver() -> Option<&'static InterruptTicketMutex u32 { - let fdt = crate::env::fdt().unwrap(); + let fdt = crate::env::start_info().fdt().unwrap(); let cpu_count = fdt.cpus().count(); u32::try_from(cpu_count).unwrap() } @@ -101,7 +103,7 @@ pub fn boot_next_processor() { #[allow(clippy::needless_return)] #[cfg(feature = "uhyve")] - if crate::env::is_uhyve() { + if crate::env::start_info().is_uhyve() { return; } @@ -125,7 +127,7 @@ pub fn boot_next_processor() { trace!("Virtual address of smp_start 0x{virt_start:x}"); trace!("Physical address of smp_start 0x{phys_start:x}"); - let fdt = crate::env::fdt().unwrap(); + let fdt = crate::env::start_info().fdt().unwrap(); let psci_node = fdt.find_node("/psci").unwrap(); let cpu_on = psci_node.property("cpu_on").unwrap().as_usize().unwrap(); diff --git a/src/arch/aarch64/kernel/pci.rs b/src/arch/aarch64/kernel/pci.rs index 18b579526f..a71a92f232 100644 --- a/src/arch/aarch64/kernel/pci.rs +++ b/src/arch/aarch64/kernel/pci.rs @@ -15,7 +15,7 @@ use crate::arch::aarch64::kernel::core_local::core_id; use crate::arch::aarch64::kernel::interrupts::GIC; use crate::arch::aarch64::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags}; use crate::drivers::pci::{PCI_DEVICES, PciDevice}; -use crate::env; +use crate::env::{self, BootInfoExt}; use crate::mm::{PageAlloc, PageRangeAllocator}; const PCI_MAX_DEVICE_NUMBER: u8 = 32; @@ -222,7 +222,7 @@ fn detect_interrupt( } pub fn init() { - let fdt = env::fdt().unwrap(); + let fdt = env::start_info().fdt().unwrap(); if let Some(pci_node) = fdt.find_compatible(&["pci-host-ecam-generic"]) { let reg = pci_node.reg().unwrap().next().unwrap(); diff --git a/src/arch/aarch64/kernel/processor.rs b/src/arch/aarch64/kernel/processor.rs index c27034b922..77fc8c1e72 100644 --- a/src/arch/aarch64/kernel/processor.rs +++ b/src/arch/aarch64/kernel/processor.rs @@ -6,6 +6,8 @@ use hermit_sync::{Lazy, OnceCell, without_interrupts}; use super::lscpu; use crate::env; +#[cfg(feature = "uhyve")] +use crate::env::BootInfoExt; /// Current FPU state. Saved at context switch when changed. /// @@ -263,7 +265,7 @@ pub fn supports_2mib_pages() -> bool { pub fn configure() { #[cfg(feature = "uhyve")] - if env::is_uhyve() { + if env::start_info().is_uhyve() { return; } diff --git a/src/arch/aarch64/kernel/start.rs b/src/arch/aarch64/kernel/start.rs index 7b6f0590f9..d76e19352f 100644 --- a/src/arch/aarch64/kernel/start.rs +++ b/src/arch/aarch64/kernel/start.rs @@ -267,7 +267,7 @@ unsafe extern "C" fn pre_init(boot_info: Option<&'static RawBootInfo>, cpu_id: u dsb(SY); if cpu_id == 0 { - env::set_boot_info(*boot_info.unwrap()); + env::set_start_info(*boot_info.unwrap()); crate::boot_processor_main() } else { #[cfg(not(feature = "smp"))] diff --git a/src/arch/aarch64/kernel/systemtime.rs b/src/arch/aarch64/kernel/systemtime.rs index 4385b468ac..22ffd0085b 100644 --- a/src/arch/aarch64/kernel/systemtime.rs +++ b/src/arch/aarch64/kernel/systemtime.rs @@ -6,7 +6,7 @@ use memory_addresses::{PhysAddr, VirtAddr}; use time::OffsetDateTime; use crate::arch::aarch64::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags}; -use crate::env; +use crate::env::{self, BootInfoExt}; use crate::mm::{PageAlloc, PageRangeAllocator}; static PL031_ADDRESS: OnceCell = OnceCell::new(); @@ -46,11 +46,11 @@ fn rtc_read(off: usize) -> u32 { fn boot_time() -> OffsetDateTime { #[cfg(feature = "uhyve")] - if let Some(boot_time) = env::uhyve_boot_time() { + if let Some(boot_time) = env::start_info().uhyve_boot_time() { return boot_time; } - let fdt = env::fdt().unwrap(); + let fdt = env::start_info().fdt().unwrap(); let Some(pl031_node) = fdt.find_compatible(&["arm,pl031"]) else { error!("Could not find PL031 Real Time Clock to determine the boot time."); return OffsetDateTime::UNIX_EPOCH; diff --git a/src/arch/riscv64/kernel/devicetree.rs b/src/arch/riscv64/kernel/devicetree.rs index 3b795c996e..907118a37d 100644 --- a/src/arch/riscv64/kernel/devicetree.rs +++ b/src/arch/riscv64/kernel/devicetree.rs @@ -43,7 +43,7 @@ use crate::drivers::virtio::transport::mmio as mmio_virtio; not(feature = "pci"), ))] use crate::drivers::virtio::transport::mmio::VirtioDriver; -use crate::env; +use crate::env::{self, BootInfoExt}; #[cfg(all(any(feature = "gem-net", feature = "virtio-net"), not(feature = "pci")))] use crate::executor::device::NETWORK_DEVICE; #[cfg(all( @@ -68,7 +68,7 @@ enum Model { /// This function should only be called once pub fn init() { debug!("Init devicetree"); - let Some(fdt) = env::fdt() else { + let Some(fdt) = env::start_info().fdt() else { return; }; @@ -106,7 +106,7 @@ pub fn init() { /// This function should only be called once pub fn init_drivers(handlers: &mut InterruptHandlerMap) { // TODO: Implement devicetree correctly - if let Some(fdt) = env::fdt() { + if let Some(fdt) = env::start_info().fdt() { debug!("Init drivers using devicetree"); unsafe { diff --git a/src/arch/riscv64/kernel/mod.rs b/src/arch/riscv64/kernel/mod.rs index de549e7aeb..7c3ca1917a 100644 --- a/src/arch/riscv64/kernel/mod.rs +++ b/src/arch/riscv64/kernel/mod.rs @@ -23,7 +23,7 @@ use crate::arch::riscv64::kernel::core_local::core_id; pub use crate::arch::riscv64::kernel::devicetree::init_drivers; use crate::arch::riscv64::kernel::processor::lsb; use crate::config::KERNEL_STACK_SIZE; -use crate::env; +use crate::env::{self, BootInfoExt}; use crate::init_cell::InitCell; use crate::mm::{FrameAlloc, PageRangeAllocator}; @@ -60,7 +60,7 @@ pub fn get_hart_mask() -> u64 { } pub fn get_timebase_freq() -> u64 { - let fdt = env::fdt().unwrap(); + let fdt = env::start_info().fdt().unwrap(); // Get timebase-freq let cpus_node = fdt @@ -150,7 +150,7 @@ pub fn boot_next_processor() { CPU_ONLINE.fetch_add(1, Ordering::Release); #[cfg(feature = "uhyve")] - if env::is_uhyve() { + if env::start_info().is_uhyve() { return; } diff --git a/src/arch/riscv64/kernel/start.rs b/src/arch/riscv64/kernel/start.rs index 0a80240462..a1824fea21 100644 --- a/src/arch/riscv64/kernel/start.rs +++ b/src/arch/riscv64/kernel/start.rs @@ -9,7 +9,7 @@ use crate::arch::riscv64::kernel::CURRENT_STACK_ADDRESS; #[cfg(not(feature = "smp"))] use crate::arch::riscv64::kernel::processor; use crate::config::KERNEL_STACK_SIZE; -use crate::env; +use crate::env::{self, BootInfoExt}; //static mut BOOT_STACK: [u8; KERNEL_STACK_SIZE] = [0; KERNEL_STACK_SIZE]; @@ -52,8 +52,8 @@ unsafe extern "C" fn pre_init(hart_id: usize, boot_info: Option<&'static RawBoot if CPU_ONLINE.load(Ordering::Acquire) == 0 { crate::logging::KERNEL_LOGGER.set_time(true); - env::set_boot_info(*boot_info.unwrap()); - let fdt = env::fdt().unwrap(); + env::set_start_info(*boot_info.unwrap()); + let fdt = env::start_info().fdt().unwrap(); // Init HART_MASK let mut hart_mask = 0; for cpu in fdt.cpus() { diff --git a/src/arch/x86_64/kernel/acpi.rs b/src/arch/x86_64/kernel/acpi.rs index e4aa03cf83..805b272a6e 100644 --- a/src/arch/x86_64/kernel/acpi.rs +++ b/src/arch/x86_64/kernel/acpi.rs @@ -11,7 +11,7 @@ use crate::arch::x86_64::mm::paging; use crate::arch::x86_64::mm::paging::{ BasePageSize, PageSize, PageTableEntryFlags, PageTableEntryFlagsExt, }; -use crate::env; +use crate::env::{self, BootInfoExt, StartInfo}; use crate::mm::{PageAlloc, PageRangeAllocator}; /// Memory at this physical address is supposed to contain a pointer to the Extended BIOS Data Area (EBDA). @@ -107,7 +107,7 @@ pub struct AcpiTable<'a> { impl AcpiTable<'_> { fn map(physical_address: PhysAddr) -> Self { - if env::is_uefi() { + if env::start_info().is_uefi() { // For UEFI Systems, the tables are already mapped so we only need to return a proper reference to the table let allocated_virtual_address = VirtAddr::new(physical_address.as_u64()); let header = unsafe { @@ -191,7 +191,7 @@ impl AcpiTable<'_> { impl Drop for AcpiTable<'_> { fn drop(&mut self) { - if !env::is_uefi() { + if !env::start_info().is_uefi() { let range = PageRange::from_start_len( self.allocated_virtual_address.as_usize(), self.allocated_length, @@ -348,7 +348,7 @@ fn detect_rsdp(start_address: PhysAddr, end_address: PhysAddr) -> Result<&'stati /// Detects ACPI support of the computer system. /// Returns a reference to the ACPI RSDP within the Ok() if successful or an empty Err() on failure. fn detect_acpi() -> Result<&'static AcpiRsdp, ()> { - if let Some(rsdp) = env::rsdp() { + if let Some(rsdp) = env::start_info().rsdp_addr() { trace!("RSDP detected successfully at {rsdp:#x?}"); let rsdp = unsafe { ptr::with_exposed_provenance::(rsdp.get()) @@ -518,7 +518,7 @@ pub fn poweroff() { pub fn init() { #[cfg(feature = "uhyve")] - if env::is_uhyve() { + if env::start_info().is_uhyve() { return; } diff --git a/src/arch/x86_64/kernel/apic.rs b/src/arch/x86_64/kernel/apic.rs index 6695a69b30..d1dcd14592 100644 --- a/src/arch/x86_64/kernel/apic.rs +++ b/src/arch/x86_64/kernel/apic.rs @@ -25,6 +25,7 @@ use crate::arch::x86_64::mm::paging::{ BasePageSize, PageSize, PageTableEntryFlags, PageTableEntryFlagsExt, }; use crate::arch::x86_64::swapgs; +use crate::env::BootInfoExt; use crate::mm::{PageAlloc, PageBox, PageRangeAllocator}; use crate::scheduler::CoreId; use crate::{arch, env, scheduler}; @@ -306,7 +307,7 @@ pub fn local_apic_id_count() -> u32 { } fn init_ioapic_address(phys_addr: PhysAddr) { - if env::is_uefi() { + if env::start_info().is_uefi() { // UEFI systems have already id mapped everything, so we can just set the physical address as the virtual one IOAPIC_ADDRESS .set(VirtAddr::new(phys_addr.as_u64())) @@ -508,7 +509,7 @@ fn default_apic() -> PhysAddr { fn apic_addr() -> PhysAddr { #[cfg(feature = "uhyve")] - if env::is_uhyve() { + if env::start_info().is_uhyve() { return default_apic(); } @@ -528,7 +529,7 @@ pub fn init() { // Initialize x2APIC or xAPIC, depending on what's available. if processor::supports_x2apic() { init_x2apic(); - } else if env::is_uefi() { + } else if env::start_info().is_uefi() { // already id mapped in UEFI systems, just use the physical address as virtual one LOCAL_APIC_ADDRESS .set(VirtAddr::new(local_apic_physical_address.as_u64())) @@ -765,7 +766,7 @@ pub fn boot_application_processors() { ); debug!("SMP boot code is {} bytes long", smp_boot_code.len()); - if env::is_uefi() { + if env::start_info().is_uefi() { // Since UEFI already provides identity-mapped pagetables, we only have to sanity-check the identity mapping let pt = unsafe { paging::identity_mapped_page_table() }; let virt_addr = SMP_BOOT_CODE_ADDRESS; diff --git a/src/arch/x86_64/kernel/mod.rs b/src/arch/x86_64/kernel/mod.rs index e0696d93a6..05056748dc 100644 --- a/src/arch/x86_64/kernel/mod.rs +++ b/src/arch/x86_64/kernel/mod.rs @@ -11,6 +11,8 @@ use x86_64::registers::control::{Cr0, Cr4}; pub(crate) use self::apic::{set_oneshot_timer, wakeup_core}; use crate::arch::x86_64::kernel::core_local::*; use crate::env; +#[cfg(feature = "uhyve")] +use crate::env::BootInfoExt; #[cfg(feature = "acpi")] pub mod acpi; @@ -41,7 +43,7 @@ pub mod vga; #[cfg(feature = "smp")] pub fn get_possible_cpus() -> u32 { #[cfg(feature = "uhyve")] - if let Some(num_cpus) = env::uhyve_num_cpus() { + if let Some(num_cpus) = env::start_info().uhyve_num_cpus() { return num_cpus.get().try_into().unwrap(); } @@ -111,7 +113,7 @@ pub fn application_processor_init() { fn finish_processor_init() { #[cfg(feature = "uhyve")] - if env::is_uhyve() { + if env::start_info().is_uhyve() { // uhyve does not use apic::detect_from_acpi and therefore does not know the number of processors and // their APIC IDs in advance. // Therefore, we have to add each booted processor into the CPU_LOCAL_APIC_IDS vector ourselves. @@ -131,7 +133,7 @@ pub fn boot_next_processor() { let cpu_online = CPU_ONLINE.fetch_add(1, Ordering::Release); #[cfg(feature = "uhyve")] - if env::is_uhyve() { + if env::start_info().is_uhyve() { return; } @@ -168,7 +170,7 @@ unsafe extern "C" fn pre_init(boot_info: Option<&'static RawBootInfo>, cpu_id: u } if cpu_id == 0 { - env::set_boot_info(*boot_info.unwrap()); + env::set_start_info(*boot_info.unwrap()); crate::boot_processor_main() } else { diff --git a/src/arch/x86_64/kernel/processor.rs b/src/arch/x86_64/kernel/processor.rs index 460c6713d8..b70fc5ed6f 100644 --- a/src/arch/x86_64/kernel/processor.rs +++ b/src/arch/x86_64/kernel/processor.rs @@ -27,7 +27,7 @@ use x86_64::{VirtAddr, instructions}; #[cfg(feature = "acpi")] use crate::arch::x86_64::kernel::acpi; use crate::arch::x86_64::kernel::{interrupts, pic, pit}; -use crate::env; +use crate::env::{self, BootInfoExt}; /// See . const MSR_PLATFORM_INFO: u32 = 0xce; @@ -352,7 +352,8 @@ impl CpuFrequency { fn detect_from_fdt(&mut self) -> Result<(), ()> { fn mhz_from_fdt() -> Option> { - let khz = env::fdt()? + let khz = env::start_info() + .fdt()? .find_node("/hermit,tsc")? .property("khz")? .as_usize()?; @@ -370,7 +371,7 @@ impl CpuFrequency { fn detect_from_hypervisor(&mut self) -> Result<(), ()> { #[cfg(feature = "uhyve")] { - let cpu_freq = env::uhyve_cpu_freq().ok_or(())?.get(); + let cpu_freq = env::start_info().uhyve_cpu_freq().ok_or(())?.get(); let mhz = cpu_freq / 1000; self.set_detected_cpu_frequency( diff --git a/src/arch/x86_64/kernel/scheduler.rs b/src/arch/x86_64/kernel/scheduler.rs index 1a31956dd0..ce3bf78e8b 100644 --- a/src/arch/x86_64/kernel/scheduler.rs +++ b/src/arch/x86_64/kernel/scheduler.rs @@ -13,7 +13,7 @@ use crate::arch::x86_64::mm::paging::{ BasePageSize, PageSize, PageTableEntryFlags, PageTableEntryFlagsExt, }; use crate::config::*; -use crate::env; +use crate::env::{self, BootInfoExt}; use crate::mm::{FrameAlloc, PageAlloc, PageRangeAllocator}; use crate::scheduler::task::{Task, TaskFrame}; use crate::scheduler::{PerCoreSchedulerExt, timer_interrupts}; @@ -220,7 +220,7 @@ impl Drop for TaskStacks { stacks.total_size >> 10, ); - if !env::is_uefi() { + if !env::start_info().is_uefi() { crate::arch::mm::paging::unmap::( stacks.virt_addr, stacks.total_size / BasePageSize::SIZE as usize + 4, diff --git a/src/arch/x86_64/kernel/systemtime.rs b/src/arch/x86_64/kernel/systemtime.rs index 43531e0f4d..294fc44f43 100644 --- a/src/arch/x86_64/kernel/systemtime.rs +++ b/src/arch/x86_64/kernel/systemtime.rs @@ -5,6 +5,8 @@ use time::OffsetDateTime; use x86_64::instructions::port::Port; use crate::arch::x86_64::kernel::processor; +#[cfg(feature = "uhyve")] +use crate::env::BootInfoExt; const CMOS_COMMAND: Port = Port::new(0x70); const CMOS_DATA: Port = Port::new(0x71); @@ -175,7 +177,7 @@ static BOOT_TIME: OnceCell = OnceCell::new(); fn boot_time() -> OffsetDateTime { #[cfg(feature = "uhyve")] - if let Some(boot_time) = crate::env::uhyve_boot_time() { + if let Some(boot_time) = crate::env::start_info().uhyve_boot_time() { return boot_time; } diff --git a/src/arch/x86_64/mm/paging.rs b/src/arch/x86_64/mm/paging.rs index aa56d2f599..bee7126a93 100644 --- a/src/arch/x86_64/mm/paging.rs +++ b/src/arch/x86_64/mm/paging.rs @@ -16,6 +16,7 @@ use x86_64::structures::paging::{ use crate::arch::x86_64::kernel::processor; use crate::arch::x86_64::mm::{PhysAddr, VirtAddr}; +use crate::env::BootInfoExt; use crate::mm::{FrameAlloc, PageRangeAllocator}; use crate::{env, scheduler}; @@ -318,7 +319,7 @@ pub fn init() { fn make_p4_writable() { debug!("Making P4 table writable"); - if !env::is_uefi() { + if !env::start_info().is_uefi() { return; } diff --git a/src/console/mod.rs b/src/console/mod.rs index 4b974d8d50..7260f82a28 100644 --- a/src/console/mod.rs +++ b/src/console/mod.rs @@ -10,6 +10,8 @@ use hermit_sync::{InterruptTicketMutex, Lazy}; use crate::arch::kernel::serial::SerialDevice; #[cfg(feature = "virtio-console")] use crate::drivers::console::VirtioUART; +#[cfg(feature = "uhyve")] +use crate::env::BootInfoExt; use crate::errno::Errno; use crate::executor::WakerRegistration; @@ -157,7 +159,7 @@ pub(crate) static CONSOLE: Lazy> = Lazy::new(|| { CoreLocal::install(); #[cfg(feature = "uhyve")] - if crate::env::is_uhyve() { + if crate::env::start_info().is_uhyve() { return InterruptTicketMutex::new(Console::new(IoDevice::Uhyve(uhyve::UhyveSerial::new()))); } diff --git a/src/env.rs b/src/env/mod.rs similarity index 56% rename from src/env.rs rename to src/env/mod.rs index 17cd879576..e9b0272cdd 100644 --- a/src/env.rs +++ b/src/env/mod.rs @@ -1,29 +1,18 @@ //! Inspection and manipulation of the kernel's environment. +mod start_info; + use alloc::borrow::ToOwned; use alloc::string::String; use alloc::vec::Vec; -use core::num::NonZero; -use core::{ptr, str}; +use core::str; use ahash::RandomState; -use fdt::Fdt; use hashbrown::HashMap; use hashbrown::hash_map::Iter; -use hermit_entry::boot_info::{BootInfo, RawBootInfo}; use hermit_sync::OnceCell; -use memory_addresses::PhysAddr; - -static BOOT_INFO: OnceCell = OnceCell::new(); - -pub fn boot_info() -> &'static BootInfo { - BOOT_INFO.get().unwrap() -} -pub fn set_boot_info(raw_boot_info: RawBootInfo) { - let boot_info = BootInfo::from(raw_boot_info); - BOOT_INFO.set(boot_info).unwrap(); -} +pub use self::start_info::*; static CLI: OnceCell = OnceCell::new(); @@ -43,93 +32,6 @@ struct Cli { mmio: Vec, } -/// Whether Hermit is running under the "uhyve" hypervisor. -#[cfg(feature = "uhyve")] -pub fn is_uhyve() -> bool { - use hermit_entry::boot_info::PlatformInfo; - - matches!(boot_info().platform_info, PlatformInfo::Uhyve { .. }) -} - -#[cfg_attr(target_arch = "riscv64", expect(dead_code))] -#[cfg(feature = "uhyve")] -pub fn uhyve_boot_time() -> Option { - use hermit_entry::boot_info::PlatformInfo; - - match boot_info().platform_info { - PlatformInfo::Uhyve { boot_time, .. } => Some(boot_time), - _ => None, - } -} - -#[cfg_attr( - any(not(target_arch = "x86_64"), not(feature = "smp")), - expect(dead_code) -)] -#[cfg(feature = "uhyve")] -pub fn uhyve_num_cpus() -> Option> { - use hermit_entry::boot_info::PlatformInfo; - - match boot_info().platform_info { - PlatformInfo::Uhyve { num_cpus, .. } => { - Some(NonZero::new(num_cpus.get() as usize).unwrap()) - } - _ => None, - } -} - -#[cfg_attr(not(target_arch = "x86_64"), expect(dead_code))] -#[cfg(feature = "uhyve")] -pub fn uhyve_cpu_freq() -> Option> { - use hermit_entry::boot_info::PlatformInfo; - - match boot_info().platform_info { - PlatformInfo::Uhyve { cpu_freq, .. } => Some(NonZero::new(cpu_freq?.get()).unwrap()), - _ => None, - } -} - -pub fn is_uefi() -> bool { - fdt().is_some_and(|fdt| fdt.root().compatible().first() == "hermit,uefi") -} - -pub fn fdt_addr() -> Option> { - boot_info() - .hardware_info - .device_tree - .map(|fdt| NonZero::new(fdt.get() as usize).unwrap()) -} - -pub fn fdt() -> Option> { - fdt_addr().map(|fdt| { - let ptr = ptr::with_exposed_provenance(fdt.get()); - unsafe { Fdt::from_ptr(ptr).unwrap() } - }) -} - -pub(crate) fn get_ram_address() -> Option { - let fdt = fdt()?; - let memory = fdt.memory(); - let ptr = memory.regions().next()?.starting_address; - Some(ptr.expose_provenance().into()) -} - -/// Returns the RSDP physical address if available. -#[cfg(all(target_arch = "x86_64", feature = "acpi"))] -pub fn rsdp() -> Option> { - let rsdp = fdt()? - .find_node("/hermit,rsdp")? - .reg()? - .next()? - .starting_address - .addr(); - NonZero::new(rsdp) -} - -pub fn fdt_args() -> Option<&'static str> { - fdt().and_then(|fdt| fdt.chosen().bootargs()) -} - impl Default for Cli { fn default() -> Self { let mut image_path = None; @@ -139,7 +41,7 @@ impl Default for Cli { RandomState::with_seeds(0, 0, 0, 0), ); - let args = fdt_args().unwrap_or_default(); + let args = start_info().bootargs().unwrap_or_default(); info!("bootargs = {args}"); let words = shell_words::split(args).unwrap(); diff --git a/src/env/start_info.rs b/src/env/start_info.rs new file mode 100644 index 0000000000..f6c9e1a94b --- /dev/null +++ b/src/env/start_info.rs @@ -0,0 +1,141 @@ +use core::num::NonZero; +use core::ptr; + +use fdt::Fdt; +use hermit_entry::boot_info::{BootInfo, RawBootInfo}; +use hermit_sync::OnceCell; + +static BOOT_INFO: OnceCell = OnceCell::new(); + +pub fn start_info() -> &'static (impl StartInfo + BootInfoExt) { + BOOT_INFO.get().unwrap() +} + +pub fn set_start_info(raw_boot_info: RawBootInfo) { + let boot_info = BootInfo::from(raw_boot_info); + BOOT_INFO.set(boot_info).unwrap(); +} + +pub trait StartInfo { + fn bootargs(&self) -> Option<&str>; + + fn first_ram_address(&self) -> usize; + + #[cfg_attr(any(target_arch = "aarch64", target_arch = "riscv64"), expect(unused))] + #[cfg(feature = "acpi")] + fn rsdp_addr(&self) -> Option>; +} + +impl StartInfo for BootInfo { + fn bootargs(&self) -> Option<&str> { + self.fdt()?.chosen().bootargs() + } + + fn first_ram_address(&self) -> usize { + self.fdt() + .unwrap() + .memory() + .regions() + .next() + .unwrap() + .starting_address + .expose_provenance() + } + + #[cfg(feature = "acpi")] + fn rsdp_addr(&self) -> Option> { + let rsdp = self + .fdt()? + .find_node("/hermit,rsdp")? + .reg()? + .next()? + .starting_address + .addr(); + NonZero::new(rsdp) + } +} + +pub trait BootInfoExt { + fn fdt(&self) -> Option>; + + fn fdt_addr(&self) -> Option>; + + fn is_uefi(&self) -> bool; + + #[cfg(feature = "uhyve")] + fn is_uhyve(&self) -> bool; + + #[cfg_attr(target_arch = "riscv64", expect(unused))] + #[cfg(feature = "uhyve")] + fn uhyve_boot_time(&self) -> Option; + + #[cfg_attr(any(target_arch = "aarch64", target_arch = "riscv64"), expect(unused))] + #[cfg(all(feature = "uhyve", feature = "smp"))] + fn uhyve_num_cpus(&self) -> Option>; + + #[cfg_attr(any(target_arch = "aarch64", target_arch = "riscv64"), expect(unused))] + #[cfg(feature = "uhyve")] + fn uhyve_cpu_freq(&self) -> Option>; +} + +impl BootInfoExt for BootInfo { + fn fdt(&self) -> Option> { + let fdt_addr = self.fdt_addr()?; + let ptr = ptr::with_exposed_provenance(fdt_addr.get()); + let fdt = unsafe { Fdt::from_ptr(ptr).unwrap() }; + Some(fdt) + } + + fn fdt_addr(&self) -> Option> { + let fdt_addr = self.hardware_info.device_tree?; + let fdt_addr = NonZero::new(fdt_addr.get() as usize).unwrap(); + Some(fdt_addr) + } + + fn is_uefi(&self) -> bool { + let Some(fdt) = self.fdt() else { + return false; + }; + + fdt.root().compatible().first() == "hermit,uefi" + } + + #[cfg(feature = "uhyve")] + fn is_uhyve(&self) -> bool { + use hermit_entry::boot_info::PlatformInfo; + + matches!(self.platform_info, PlatformInfo::Uhyve { .. }) + } + + #[cfg(feature = "uhyve")] + fn uhyve_boot_time(&self) -> Option { + use hermit_entry::boot_info::PlatformInfo; + + match self.platform_info { + PlatformInfo::Uhyve { boot_time, .. } => Some(boot_time), + _ => None, + } + } + + #[cfg(all(feature = "uhyve", feature = "smp"))] + fn uhyve_num_cpus(&self) -> Option> { + use hermit_entry::boot_info::PlatformInfo; + + match self.platform_info { + PlatformInfo::Uhyve { num_cpus, .. } => { + Some(NonZero::new(num_cpus.get() as usize).unwrap()) + } + _ => None, + } + } + + #[cfg(feature = "uhyve")] + fn uhyve_cpu_freq(&self) -> Option> { + use hermit_entry::boot_info::PlatformInfo; + + match self.platform_info { + PlatformInfo::Uhyve { cpu_freq, .. } => Some(NonZero::new(cpu_freq?.get()).unwrap()), + _ => None, + } + } +} diff --git a/src/fd/stdio/mod.rs b/src/fd/stdio/mod.rs index 00692d4218..9f755da2b8 100644 --- a/src/fd/stdio/mod.rs +++ b/src/fd/stdio/mod.rs @@ -14,11 +14,13 @@ use hashbrown::HashMap; pub use self::console::{ConsoleStderr, ConsoleStdin, ConsoleStdout}; #[cfg(feature = "uhyve")] pub use self::uhyve::{UhyveStderr, UhyveStdin, UhyveStdout}; +#[cfg(feature = "uhyve")] +use crate::env::BootInfoExt; use crate::fd::{Fd, RawFd, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO}; pub(crate) fn setup(fds: &mut HashMap>, RandomState>) { #[cfg(feature = "uhyve")] - if crate::env::is_uhyve() { + if crate::env::start_info().is_uhyve() { let stdin = Arc::new(async_lock::RwLock::new(UhyveStdin::new().into())); let stdout = Arc::new(async_lock::RwLock::new(UhyveStdout::new().into())); let stderr = Arc::new(async_lock::RwLock::new(UhyveStderr::new().into())); diff --git a/src/fs/mod.rs b/src/fs/mod.rs index 8ef50ad0c7..23aaf08ce5 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -19,6 +19,8 @@ use hermit_sync::{InterruptSpinMutex, OnceCell}; use mem::MemDirectory; use num_enum::{IntoPrimitive, TryFromPrimitive}; +#[cfg(feature = "uhyve")] +use crate::env::BootInfoExt; use crate::errno::Errno; use crate::executor::block_on; use crate::fd::{AccessPermission, Fd, ObjectInterface, OpenOption, insert_object, remove_object}; @@ -332,7 +334,7 @@ pub(crate) fn init() { virtio_fs::init(); #[cfg(feature = "uhyve")] - if crate::env::is_uhyve() { + if crate::env::start_info().is_uhyve() { uhyve::init(); } diff --git a/src/fs/uhyve.rs b/src/fs/uhyve.rs index 3895c0020d..d815677d45 100644 --- a/src/fs/uhyve.rs +++ b/src/fs/uhyve.rs @@ -14,14 +14,14 @@ use uhyve_interface::v2::parameters::{ }; use crate::arch::mm::paging; -use crate::env::fdt; +use crate::env::BootInfoExt; use crate::errno::Errno; use crate::fd::{Fd, RawFd}; use crate::fs::{ self, AccessPermission, FileAttr, NodeKind, ObjectInterface, OpenOption, SeekWhence, VfsNode, }; -use crate::io; use crate::uhyve::uhyve_hypercall; +use crate::{env, io}; #[derive(Debug)] struct UhyveFileHandleInner(i32); @@ -242,7 +242,7 @@ impl VfsNode for UhyveDirectory { pub(crate) fn init() { info!("Try to initialize uhyve filesystem"); - let mount_str = fdt().and_then(|fdt| { + let mount_str = env::start_info().fdt().and_then(|fdt| { fdt.find_node("/uhyve,mounts") .and_then(|node| node.property("mounts")) .and_then(|property| property.as_str()) diff --git a/src/lib.rs b/src/lib.rs index 25745c5744..128ea45140 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -227,6 +227,7 @@ fn synch_all_cores() { #[cfg(target_os = "none")] fn boot_processor_main() -> ! { use crate::config::USER_STACK_SIZE; + use crate::env::BootInfoExt; // Initialize the kernel and hardware. mm::claim_initial_heap(); @@ -263,7 +264,7 @@ fn boot_processor_main() -> ! { info!("Data segment end: {:p}", elf_symbols::data_end()); info!("Executable end: {:p}", elf_symbols::executable_end()); - if let Some(fdt) = env::fdt() { + if let Some(fdt) = env::start_info().fdt() { info!("FDT:\n{fdt:#?}"); } diff --git a/src/mm/mod.rs b/src/mm/mod.rs index 9f16f4104f..9192f0064d 100644 --- a/src/mm/mod.rs +++ b/src/mm/mod.rs @@ -65,6 +65,8 @@ pub use self::virtualmem::{PageAlloc, PageBox}; use crate::arch::mm::paging::HugePageSize; pub use crate::arch::mm::paging::virtual_to_physical; use crate::arch::mm::paging::{BasePageSize, LargePageSize, PageSize}; +#[cfg(target_os = "none")] +use crate::env::{BootInfoExt, StartInfo}; use crate::{arch, env}; #[cfg(target_os = "none")] @@ -142,12 +144,11 @@ pub(crate) fn init() { let has_1gib_pages = arch::kernel::processor::supports_1gib_pages(); let has_2mib_pages = arch::kernel::processor::supports_2mib_pages(); - let min_mem = if env::is_uefi() { + let min_mem = if env::start_info().is_uefi() { // On UEFI, the given memory is guaranteed free memory and the kernel is located before the given memory reserved_space } else { - (kernel_addr_range.end.as_u64() - env::get_ram_address().unwrap().as_u64() - + reserved_space as u64) as usize + kernel_addr_range.end.as_usize() - env::start_info().first_ram_address() + reserved_space }; info!("Minimum memory size: {} MiB", min_mem >> 20); let avail_mem = total_mem diff --git a/src/mm/physicalmem.rs b/src/mm/physicalmem.rs index 758871230c..c7659f425c 100644 --- a/src/mm/physicalmem.rs +++ b/src/mm/physicalmem.rs @@ -10,7 +10,7 @@ use memory_addresses::{PhysAddr, VirtAddr}; #[cfg(target_arch = "x86_64")] use crate::arch::mm::paging::PageTableEntryFlagsExt; use crate::arch::mm::paging::{self, HugePageSize, PageSize, PageTableEntryFlags}; -use crate::env; +use crate::env::{self, BootInfoExt}; use crate::mm::device_alloc::DeviceAlloc; use crate::mm::{PageRangeAllocator, PageRangeBox}; @@ -104,7 +104,7 @@ pub unsafe fn map_frame_range(frame_range: PageRange) { } unsafe fn detect_from_fdt() -> Result<(), ()> { - let fdt = env::fdt().ok_or(())?; + let fdt = env::start_info().fdt().ok_or(())?; let all_regions = fdt .find_all_nodes("/memory") @@ -121,16 +121,17 @@ unsafe fn detect_from_fdt() -> Result<(), ()> { let size = m.size.unwrap() as u64; let end_address = start_address + size; - if end_address <= super::kernel_end_address().as_u64() && !env::is_uefi() { + if end_address <= super::kernel_end_address().as_u64() && !env::start_info().is_uefi() { continue; } - let start_address = - if start_address <= super::kernel_start_address().as_u64() && !env::is_uefi() { - super::kernel_end_address() - } else { - VirtAddr::new(start_address) - }; + let start_address = if start_address <= super::kernel_start_address().as_u64() + && !env::start_info().is_uefi() + { + super::kernel_end_address() + } else { + VirtAddr::new(start_address) + }; let range = PageRange::new(start_address.as_usize(), end_address as usize).unwrap(); unsafe { @@ -160,7 +161,7 @@ unsafe fn detect_from_fdt() -> Result<(), ()> { reserve(reservation); } - let kernel_start = if env::is_uefi() { + let kernel_start = if env::start_info().is_uefi() { super::kernel_start_address().as_usize() } else { // FIXME: Memory before the kernel causes trouble on non-uefi systems. @@ -171,7 +172,7 @@ unsafe fn detect_from_fdt() -> Result<(), ()> { let kernel_region = PageRange::new(kernel_start, kernel_end).unwrap(); reserve(kernel_region); - let fdt_start = env::fdt_addr().unwrap().get(); + let fdt_start = env::start_info().fdt_addr().unwrap().get(); let fdt_end = fdt_start + fdt.total_size(); let fdt_region = PageRange::containing(fdt_start, fdt_end).unwrap(); reserve(fdt_region); @@ -201,7 +202,7 @@ impl PageRangeExt for PageRange { } unsafe fn init() { - if env::is_uefi() && DeviceAlloc.phys_offset() != VirtAddr::zero() { + if env::start_info().is_uefi() && DeviceAlloc.phys_offset() != VirtAddr::zero() { let start = DeviceAlloc.phys_offset(); let count = DeviceAlloc.phys_offset().as_u64() / HugePageSize::SIZE; let count = usize::try_from(count).unwrap(); diff --git a/src/syscalls/mod.rs b/src/syscalls/mod.rs index b0c7dff8d6..87dc4e2662 100644 --- a/src/syscalls/mod.rs +++ b/src/syscalls/mod.rs @@ -21,6 +21,8 @@ pub use self::spinlock::*; pub use self::system::*; pub use self::tasks::*; pub use self::timer::*; +#[cfg(feature = "uhyve")] +use crate::env::BootInfoExt; use crate::errno::{Errno, ToErrno}; use crate::executor::block_on; use crate::fd::{ @@ -266,7 +268,7 @@ pub(crate) fn shutdown(arg: i32) -> ! { crate::arch::kernel::print_statistics(); #[cfg(feature = "uhyve")] - if env::is_uhyve() { + if env::start_info().is_uhyve() { crate::uhyve::shutdown(arg); }