diff --git a/src/arch/aarch64/kernel/interrupts.rs b/src/arch/aarch64/kernel/interrupts.rs index 53792c0f65..d1401cc090 100644 --- a/src/arch/aarch64/kernel/interrupts.rs +++ b/src/arch/aarch64/kernel/interrupts.rs @@ -19,7 +19,7 @@ use crate::arch::kernel::scheduler::State; use crate::arch::kernel::serial::handle_uart_interrupt; use crate::arch::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 55813b0e17..817a0707b4 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() } @@ -99,7 +101,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; } @@ -123,7 +125,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 f3b40d3916..c181c050ca 100644 --- a/src/arch/aarch64/kernel/pci.rs +++ b/src/arch/aarch64/kernel/pci.rs @@ -15,7 +15,7 @@ use crate::arch::kernel::core_local::core_id; use crate::arch::kernel::interrupts::GIC; use crate::arch::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 c7a4a7524a..0e75f5c3c8 100644 --- a/src/arch/aarch64/kernel/processor.rs +++ b/src/arch/aarch64/kernel/processor.rs @@ -7,6 +7,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. /// @@ -268,7 +270,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/systemtime.rs b/src/arch/aarch64/kernel/systemtime.rs index 417827258f..6b56e4c3a0 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::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/aarch64/start/hermit_entry.rs b/src/arch/aarch64/start/hermit_entry.rs index c03577bea5..a0290654e6 100644 --- a/src/arch/aarch64/start/hermit_entry.rs +++ b/src/arch/aarch64/start/hermit_entry.rs @@ -91,7 +91,7 @@ pub unsafe extern "C" fn pre_init(boot_info: Option<&'static RawBootInfo>, cpu_i dsb(SY); if cpu_id == 0 { - env::set_boot_info(*boot_info.unwrap()); + env::set_start_info(*boot_info.unwrap()); crate::rt::boot_processor_main() } else { #[cfg(not(feature = "smp"))] diff --git a/src/arch/riscv64/kernel/devicetree.rs b/src/arch/riscv64/kernel/devicetree.rs index 4c1f3905ee..52ebaa70f3 100644 --- a/src/arch/riscv64/kernel/devicetree.rs +++ b/src/arch/riscv64/kernel/devicetree.rs @@ -52,7 +52,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; @@ -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 d55033ac1c..a7ac4d4174 100644 --- a/src/arch/riscv64/kernel/mod.rs +++ b/src/arch/riscv64/kernel/mod.rs @@ -22,7 +22,7 @@ use crate::arch::kernel::core_local::core_id; pub use crate::arch::kernel::devicetree::init_drivers; use crate::arch::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}; @@ -59,7 +59,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() { #[allow(clippy::needless_return)] #[cfg(feature = "uhyve")] - if env::is_uhyve() { + if env::start_info().is_uhyve() { return; } diff --git a/src/arch/riscv64/start/hermit_entry.rs b/src/arch/riscv64/start/hermit_entry.rs index d60f9ff257..cd37f59737 100644 --- a/src/arch/riscv64/start/hermit_entry.rs +++ b/src/arch/riscv64/start/hermit_entry.rs @@ -11,6 +11,7 @@ use crate::arch::kernel::{ }; use crate::config::KERNEL_STACK_SIZE; use crate::env; +use crate::env::BootInfoExt; //static mut BOOT_STACK: [u8; KERNEL_STACK_SIZE] = [0; KERNEL_STACK_SIZE]; @@ -53,8 +54,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 a01cd21fad..3db0c88ab7 100644 --- a/src/arch/x86_64/kernel/acpi.rs +++ b/src/arch/x86_64/kernel/acpi.rs @@ -11,7 +11,7 @@ use crate::arch::mm::paging; use crate::arch::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 7c33db2720..560ec7eb65 100644 --- a/src/arch/x86_64/kernel/apic.rs +++ b/src/arch/x86_64/kernel/apic.rs @@ -25,6 +25,7 @@ use crate::arch::mm::paging::{ BasePageSize, PageSize, PageTableEntryFlags, PageTableEntryFlagsExt, }; use crate::arch::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())) @@ -764,7 +765,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 59cfce8ef9..906d3857c3 100644 --- a/src/arch/x86_64/kernel/mod.rs +++ b/src/arch/x86_64/kernel/mod.rs @@ -9,6 +9,8 @@ use x86_64::registers::control::{Cr0, Cr4}; pub(crate) use self::apic::{set_oneshot_timer, wakeup_core}; use crate::arch::kernel::core_local::*; +#[cfg(feature = "uhyve")] +use crate::env::{self, BootInfoExt}; #[cfg(feature = "acpi")] pub mod acpi; @@ -37,7 +39,7 @@ pub mod vga; #[cfg(feature = "smp")] pub fn get_possible_cpus() -> u32 { #[cfg(feature = "uhyve")] - if let Some(num_cpus) = crate::env::uhyve_num_cpus() { + if let Some(num_cpus) = env::start_info().uhyve_num_cpus() { return num_cpus.get().try_into().unwrap(); } @@ -107,7 +109,7 @@ pub fn application_processor_init() { fn finish_processor_init() { #[cfg(feature = "uhyve")] - if crate::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. @@ -127,7 +129,7 @@ pub fn boot_next_processor() { let cpu_online = CPU_ONLINE.fetch_add(1, Ordering::Release); #[cfg(feature = "uhyve")] - if crate::env::is_uhyve() { + if env::start_info().is_uhyve() { return; } diff --git a/src/arch/x86_64/kernel/processor.rs b/src/arch/x86_64/kernel/processor.rs index 747b0e8a3e..f998c7f2a4 100644 --- a/src/arch/x86_64/kernel/processor.rs +++ b/src/arch/x86_64/kernel/processor.rs @@ -354,8 +354,11 @@ impl CpuFrequency { { use core::num::NonZero; + use crate::env::BootInfoExt; + fn mhz_from_fdt() -> Option> { - let khz = env::fdt()? + let khz = env::start_info() + .fdt()? .find_node("/hermit,tsc")? .property("khz")? .as_usize()?; diff --git a/src/arch/x86_64/kernel/systemtime.rs b/src/arch/x86_64/kernel/systemtime.rs index edc0c9caa7..f27bd54ee2 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::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 b99cdf854d..2d49b1b358 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::kernel::processor; use crate::arch::mm::{PhysAddr, VirtAddr}; +use crate::env::BootInfoExt; use crate::mm::{FrameAlloc, PageRangeAllocator}; use crate::{env, scheduler}; @@ -313,7 +314,7 @@ pub fn init() { log_page_tables(); } - if env::is_uefi() { + if env::start_info().is_uefi() { make_p4_writable(); } } diff --git a/src/arch/x86_64/start/hermit_entry.rs b/src/arch/x86_64/start/hermit_entry.rs index c05b13fe02..1858fdac79 100644 --- a/src/arch/x86_64/start/hermit_entry.rs +++ b/src/arch/x86_64/start/hermit_entry.rs @@ -76,7 +76,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::rt::boot_processor_main() } else { 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 62% rename from src/env.rs rename to src/env/mod.rs index 38d6f83056..7f09c778cb 100644 --- a/src/env.rs +++ b/src/env/mod.rs @@ -1,29 +1,19 @@ //! 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 shlex::Shlex; -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,75 +33,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, - } -} - -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() } - }) -} - -/// 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; @@ -121,7 +42,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 mut words = Shlex::new(args); diff --git a/src/env/start_info/hermit_entry.rs b/src/env/start_info/hermit_entry.rs new file mode 100644 index 0000000000..da5b3f6757 --- /dev/null +++ b/src/env/start_info/hermit_entry.rs @@ -0,0 +1,108 @@ +use core::num::NonZero; +use core::ptr; + +use fdt::Fdt; +use hermit_entry::boot_info::{BootInfo, RawBootInfo}; +use hermit_sync::OnceCell; + +use super::StartInfo; + +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(); +} + +impl StartInfo for BootInfo { + fn bootargs(&self) -> Option<&str> { + self.fdt()?.chosen().bootargs() + } + + #[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>; +} + +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, + } + } +} diff --git a/src/env/start_info/mod.rs b/src/env/start_info/mod.rs new file mode 100644 index 0000000000..14aa867eab --- /dev/null +++ b/src/env/start_info/mod.rs @@ -0,0 +1,11 @@ +mod hermit_entry; + +pub use hermit_entry::{BootInfoExt, set_start_info, start_info}; + +pub trait StartInfo { + fn bootargs(&self) -> Option<&str>; + + #[cfg_attr(any(target_arch = "aarch64", target_arch = "riscv64"), expect(unused))] + #[cfg(feature = "acpi")] + fn rsdp_addr(&self) -> Option>; +} 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 54c177b50e..d815677d45 100644 --- a/src/fs/uhyve.rs +++ b/src/fs/uhyve.rs @@ -14,6 +14,7 @@ use uhyve_interface::v2::parameters::{ }; use crate::arch::mm::paging; +use crate::env::BootInfoExt; use crate::errno::Errno; use crate::fd::{Fd, RawFd}; use crate::fs::{ @@ -241,7 +242,7 @@ impl VfsNode for UhyveDirectory { pub(crate) fn init() { info!("Try to initialize uhyve filesystem"); - let mount_str = env::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/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/rt.rs b/src/rt.rs index ea1ef7ec73..0769230e25 100644 --- a/src/rt.rs +++ b/src/rt.rs @@ -1,6 +1,7 @@ use crate::arch::kernel; use crate::arch::kernel::core_local::{core_id, core_scheduler}; use crate::arch::kernel::interrupts; +use crate::env::BootInfoExt; use crate::scheduler::{PerCoreScheduler, PerCoreSchedulerExt}; use crate::{console, drivers, env, executor, fs, logging, mm, scheduler, syscalls}; @@ -135,7 +136,7 @@ pub 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/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); }