diff --git a/Cargo.toml b/Cargo.toml index cfb3d84b..40c95020 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ opt-level = 3 [dependencies] yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } vfs = { path = "lib/vfs" } +# TODO move to drivers memfs = { path = "lib/memfs" } device-api = { path = "lib/device-api", features = ["derive"] } kernel-util = { path = "lib/kernel-util" } @@ -20,6 +21,8 @@ device-api-macros = { path = "lib/device-api/macros" } # Drivers ygg_driver_pci = { path = "driver/bus/pci" } +ygg_driver_nvme = { path = "driver/block/nvme" } +kernel-fs = { path = "driver/fs/kernel-fs" } atomic_enum = "0.2.0" bitflags = "2.3.3" diff --git a/driver/block/nvme/Cargo.toml b/driver/block/nvme/Cargo.toml new file mode 100644 index 00000000..ca5721ce --- /dev/null +++ b/driver/block/nvme/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "ygg_driver_nvme" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } +kernel-util = { path = "../../../lib/kernel-util" } +device-api = { path = "../../../lib/device-api", features = ["derive"] } +vfs = { path = "../../../lib/vfs" } + +ygg_driver_pci = { path = "../../bus/pci" } +kernel-fs = { path = "../../fs/kernel-fs" } + +log = "0.4.20" +futures-util = { version = "0.3.28", default-features = false, features = ["alloc", "async-await"] } +static_assertions = "1.1.0" +tock-registers = "0.8.1" +bytemuck = { version = "1.14.0", features = ["derive"] } diff --git a/src/device/nvme/command.rs b/driver/block/nvme/src/command.rs similarity index 99% rename from src/device/nvme/command.rs rename to driver/block/nvme/src/command.rs index 0759de59..d3eb069e 100644 --- a/src/device/nvme/command.rs +++ b/driver/block/nvme/src/command.rs @@ -5,7 +5,7 @@ use core::fmt::{self, Write}; use kernel_util::mem::address::PhysicalAddress; use tock_registers::{interfaces::Readable, register_structs, registers::ReadOnly, UIntLike}; -use crate::device::nvme::queue::PhysicalRegionPage; +use crate::queue::PhysicalRegionPage; use super::queue::SubmissionQueueEntry; diff --git a/src/device/nvme/drive.rs b/driver/block/nvme/src/drive.rs similarity index 90% rename from src/device/nvme/drive.rs rename to driver/block/nvme/src/drive.rs index be2daf60..559d61c0 100644 --- a/src/device/nvme/drive.rs +++ b/driver/block/nvme/src/drive.rs @@ -1,8 +1,9 @@ -use abi::{error::Error, io::DeviceRequest}; use alloc::{boxed::Box, format}; +use kernel_fs::devfs; use vfs::BlockDevice; +use yggdrasil_abi::{error::Error, io::DeviceRequest}; -use crate::{device::nvme::command::IdentifyNamespaceRequest, fs::devfs}; +use crate::command::IdentifyNamespaceRequest; use super::{error::NvmeError, NvmeController}; @@ -27,7 +28,7 @@ impl NvmeDrive { let lba_size = current_lba_format.lba_data_size().unwrap(); let total_lba_count = identify.total_lba_count(); - debugln!( + log::debug!( "ns = {}, lba = {}B, size = {}M", nsid, lba_size, @@ -41,7 +42,6 @@ impl NvmeDrive { lba_size, })); - // TODO add the drive as a block device let node_name = format!("nvme{}n{}", controller.controller_id.get(), nsid); devfs::add_named_block_device(dev, node_name).ok(); diff --git a/src/device/nvme/error.rs b/driver/block/nvme/src/error.rs similarity index 88% rename from src/device/nvme/error.rs rename to driver/block/nvme/src/error.rs index 86553300..e933f039 100644 --- a/src/device/nvme/error.rs +++ b/driver/block/nvme/src/error.rs @@ -1,4 +1,4 @@ -use abi::error::Error; +use yggdrasil_abi::error::Error; use super::queue::CommandError; diff --git a/src/device/nvme/mod.rs b/driver/block/nvme/src/lib.rs similarity index 93% rename from src/device/nvme/mod.rs rename to driver/block/nvme/src/lib.rs index f54a3288..42013079 100644 --- a/src/device/nvme/mod.rs +++ b/driver/block/nvme/src/lib.rs @@ -1,15 +1,21 @@ +#![feature(strict_provenance, const_trait_impl)] #![allow(missing_docs)] +#![no_std] + +extern crate alloc; + use core::{mem::size_of, time::Duration}; -use abi::error::Error; use alloc::{boxed::Box, collections::BTreeMap, vec::Vec}; +use command::{IdentifyActiveNamespaceIdListRequest, IdentifyControllerRequest}; use device_api::{interrupt::MsiHandler, Device}; +use drive::NvmeDrive; use kernel_util::{ mem::{ address::{FromRaw, IntoRaw, PhysicalAddress}, device::{DeviceMemoryIo, DeviceMemoryIoMut}, }, - runtime, + message_interrupt_controller, runtime, sync::IrqSafeSpinlock, util::OneTimeInit, }; @@ -22,16 +28,11 @@ use ygg_driver_pci::{ capability::{MsiXCapability, MsiXEntry}, PciBaseAddress, PciCommandRegister, PciConfigurationSpace, PciDeviceInfo, }; +use yggdrasil_abi::error::Error; use crate::{ - arch::{Architecture, ARCHITECTURE}, - device::nvme::{ - command::{ - IdentifyActiveNamespaceIdListRequest, IdentifyControllerRequest, IoRead, IoWrite, - }, - drive::NvmeDrive, - queue::{CompletionQueueEntry, SubmissionQueueEntry}, - }, + command::{IoRead, IoWrite}, + queue::{CompletionQueueEntry, SubmissionQueueEntry}, }; use self::{ @@ -199,7 +200,7 @@ impl NvmeController { self.drive_table.lock().insert(nsid, drive); } Err(error) => { - warnln!("Could not create nvme drive, nsid={}: {:?}", nsid, error); + log::warn!("Could not create nvme drive, nsid={}: {:?}", nsid, error); } } } @@ -217,7 +218,7 @@ impl NvmeController { ) -> Result<(), NvmeError> { let ioq = &self.ioqs.get()[0]; - debugln!("{:?} nsid={}, lba={:#x}", direction, nsid, lba); + log::debug!("{:?} nsid={}, lba={:#x}", direction, nsid, lba); let cmd_id = match direction { IoDirection::Read => ioq.submit( IoRead { @@ -276,7 +277,7 @@ impl Device for NvmeController { } let timeout = Duration::from_millis(regs.CAP.read(CAP::TO) * 500); - debugln!("Worst-case timeout: {:?}", timeout); + log::debug!("Worst-case timeout: {:?}", timeout); while regs.CSTS.matches_any(CSTS::RDY::SET) { core::hint::spin_loop(); @@ -293,7 +294,7 @@ impl Device for NvmeController { // Setup the admin queue (index 0) let admin_sq_doorbell = unsafe { regs.doorbell_ptr(self.doorbell_shift, false, 0) }; let admin_cq_doorbell = unsafe { regs.doorbell_ptr(self.doorbell_shift, true, 0) }; - debugln!("sq_doorbell for adminq = {:p}", admin_sq_doorbell); + log::debug!("sq_doorbell for adminq = {:p}", admin_sq_doorbell); let admin_q = QueuePair::new( 0, 0, @@ -322,7 +323,7 @@ impl Device for NvmeController { // Enable the controller regs.CC.modify(CC::ENABLE::SET); - debugln!("Reset the controller"); + log::debug!("Reset the controller"); while !regs.CSTS.matches_any(CSTS::RDY::SET + CSTS::CFS::SET) { core::hint::spin_loop(); @@ -340,7 +341,7 @@ impl Device for NvmeController { // Register vector 0 vt[0] - .register(ARCHITECTURE.message_interrupt_controller(), self) + .register(message_interrupt_controller(), self) .unwrap(); } diff --git a/src/device/nvme/queue.rs b/driver/block/nvme/src/queue.rs similarity index 98% rename from src/device/nvme/queue.rs rename to driver/block/nvme/src/queue.rs index 1381c481..0688bec2 100644 --- a/src/device/nvme/queue.rs +++ b/driver/block/nvme/src/queue.rs @@ -5,7 +5,6 @@ use core::{ task::{Context, Poll}, }; -use abi::error::Error; use alloc::{ collections::{BTreeMap, BTreeSet}, vec::Vec, @@ -21,6 +20,7 @@ use kernel_util::{ sync::IrqSafeSpinlock, }; use static_assertions::const_assert; +use yggdrasil_abi::error::Error; use super::{ command::{Command, Request}, @@ -252,7 +252,7 @@ impl QueuePair { let sq_base = unsafe { sq_data.as_physical_address() }; let cq_base = unsafe { cq_data.as_physical_address() }; - debugln!("Allocated queue pair: sq={:p}, cq={:p}", sq_data, cq_data); + log::debug!("Allocated queue pair: sq={:p}, cq={:p}", sq_data, cq_data); let sq = Queue::new(sq_data, null_mut(), sq_doorbell, true); let cq = Queue::new(cq_data, cq_doorbell, null_mut(), true); diff --git a/driver/fs/kernel-fs/Cargo.toml b/driver/fs/kernel-fs/Cargo.toml new file mode 100644 index 00000000..59a737ee --- /dev/null +++ b/driver/fs/kernel-fs/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "kernel-fs" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } +vfs = { path = "../../../lib/vfs" } +kernel-util = { path = "../../../lib/kernel-util" } + +log = "0.4.20" diff --git a/src/fs/devfs.rs b/driver/fs/kernel-fs/src/devfs.rs similarity index 76% rename from src/fs/devfs.rs rename to driver/fs/kernel-fs/src/devfs.rs index 74f9651d..8cdd6955 100644 --- a/src/fs/devfs.rs +++ b/driver/fs/kernel-fs/src/devfs.rs @@ -1,15 +1,10 @@ //! Device virtual file system use core::sync::atomic::{AtomicUsize, Ordering}; -use abi::error::Error; use alloc::{format, string::String}; use kernel_util::util::OneTimeInit; -use vfs::{ - impls::{read_fn_node, MemoryDirectory}, - BlockDevice, CharDevice, Node, NodeFlags, NodeRef, -}; - -use crate::proc::random; +use vfs::{impls::MemoryDirectory, BlockDevice, CharDevice, Node, NodeFlags, NodeRef}; +use yggdrasil_abi::error::Error; /// Describes the kind of a character device #[derive(Debug)] @@ -39,7 +34,7 @@ pub fn root() -> &'static NodeRef { /// Adds a character device with a custom name pub fn add_named_char_device(dev: &'static dyn CharDevice, name: String) -> Result<(), Error> { - infoln!("Add char device: {}", name); + log::info!("Add char device: {}", name); let node = Node::char(dev, NodeFlags::IN_MEMORY_PROPS); @@ -52,7 +47,7 @@ pub fn add_named_block_device>( name: S, ) -> Result<(), Error> { let name = name.into(); - infoln!("Add block device: {}", name); + log::info!("Add block device: {}", name); let node = Node::block(dev, NodeFlags::IN_MEMORY_PROPS); @@ -74,16 +69,3 @@ pub fn add_char_device(dev: &'static dyn CharDevice, kind: CharDeviceType) -> Re add_named_char_device(dev, name) } - -/// Adds "pseudo"-devices to the filesystem (i.e. /dev/random) -pub fn add_pseudo_devices() -> Result<(), Error> { - let random = read_fn_node(move |_, buf| { - random::read(buf); - Ok(buf.len()) - }); - - let root = root(); - root.add_child("random", random)?; - - Ok(()) -} diff --git a/driver/fs/kernel-fs/src/lib.rs b/driver/fs/kernel-fs/src/lib.rs new file mode 100644 index 00000000..22b952ff --- /dev/null +++ b/driver/fs/kernel-fs/src/lib.rs @@ -0,0 +1,5 @@ +#![no_std] + +extern crate alloc; + +pub mod devfs; diff --git a/lib/kernel-util/Cargo.toml b/lib/kernel-util/Cargo.toml index 781b9149..c953eeaf 100644 --- a/lib/kernel-util/Cargo.toml +++ b/lib/kernel-util/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } +device-api = { path = "../device-api", features = ["derive"] } log = "0.4.20" futures-util = { version = "0.3.28", default-features = false, features = ["alloc", "async-await"] } diff --git a/lib/kernel-util/src/api.rs b/lib/kernel-util/src/api.rs index b391d89c..0a3c3b2f 100644 --- a/lib/kernel-util/src/api.rs +++ b/lib/kernel-util/src/api.rs @@ -1,6 +1,7 @@ use core::time::Duration; use alloc::{string::String, sync::Arc}; +use device_api::interrupt::MessageInterruptController; use yggdrasil_abi::{error::Error, process::ExitCode}; use crate::{ @@ -39,4 +40,6 @@ extern "Rust" { pub fn __exit_current(t: &CurrentThread, code: ExitCode) -> !; pub fn __monotonic_timestamp() -> Result; + + pub fn __message_interrupt_controller() -> &'static dyn MessageInterruptController; } diff --git a/lib/kernel-util/src/lib.rs b/lib/kernel-util/src/lib.rs index 573a8066..be09a9bc 100644 --- a/lib/kernel-util/src/lib.rs +++ b/lib/kernel-util/src/lib.rs @@ -10,6 +10,8 @@ let_chains )] +use device_api::interrupt::MessageInterruptController; + extern crate alloc; pub(crate) mod api; @@ -20,6 +22,11 @@ pub mod sync; pub mod thread; pub mod util; +#[inline] +pub fn message_interrupt_controller() -> &'static dyn MessageInterruptController { + unsafe { api::__message_interrupt_controller() } +} + #[repr(C)] pub struct AlignedTo { pub align: [Align; 0], diff --git a/src/arch/mod.rs b/src/arch/mod.rs index f16783a4..2b259669 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -271,3 +271,8 @@ fn __unmap_device_pages(mapping: &RawDeviceMemoryMapping) { fn __monotonic_timestamp() -> Result { ARCHITECTURE.monotonic_timer().monotonic_timestamp() } + +#[no_mangle] +fn __message_interrupt_controller() -> &'static dyn MessageInterruptController { + ARCHITECTURE.message_interrupt_controller() +} diff --git a/src/arch/x86_64/boot/mod.rs b/src/arch/x86_64/boot/mod.rs index c41b561b..f7b891ca 100644 --- a/src/arch/x86_64/boot/mod.rs +++ b/src/arch/x86_64/boot/mod.rs @@ -1,6 +1,7 @@ //! x86-64 boot and entry functions use core::{arch::global_asm, sync::atomic::Ordering}; +use kernel_fs::devfs; use kernel_util::runtime; use tock_registers::interfaces::Writeable; use yboot_proto::{ @@ -10,7 +11,6 @@ use yboot_proto::{ use crate::{ arch::x86_64::{registers::MSR_IA32_KERNEL_GS_BASE, smp::CPU_COUNT}, - fs::devfs, kernel_main, kernel_secondary_main, mem::KERNEL_VIRT_OFFSET, }; diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 5834257c..6e315029 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -11,6 +11,7 @@ use device_api::{ Device, }; use git_version::git_version; +use kernel_fs::devfs::{self, CharDeviceType}; use kernel_util::{ mem::{ address::{FromRaw, IntoRaw, PhysicalAddress}, @@ -51,13 +52,9 @@ use crate::{ device::{ self, display::{console, fb_console::FramebufferConsole, linear_fb::LinearFramebuffer}, - nvme, tty::CombinedTerminal, }, - fs::{ - devfs::{self, CharDeviceType}, - Initrd, INITRD_DATA, - }, + fs::{Initrd, INITRD_DATA}, mem::{ heap, phys::{self, reserved::reserve_region, PhysicalMemoryRegion}, @@ -392,7 +389,7 @@ impl X86_64 { 0x01, Some(0x08), Some(0x02), - nvme::probe, + ygg_driver_nvme::probe, ); match self.boot_data.get() { diff --git a/src/device/mod.rs b/src/device/mod.rs index e5c73988..7fa4d9e5 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -10,8 +10,6 @@ pub mod devtree; #[cfg(not(target_arch = "aarch64"))] pub mod bus; -pub mod nvme; - pub mod display; pub mod power; pub mod serial; diff --git a/src/fs/mod.rs b/src/fs/mod.rs index 994a4012..22811030 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -2,14 +2,15 @@ use core::ptr::NonNull; +use kernel_fs::devfs; use kernel_util::{mem::address::PhysicalAddress, util::OneTimeInit}; use memfs::block::{self, BlockAllocator}; -use vfs::NodeRef; +use vfs::{impls::read_fn_node, NodeRef}; use yggdrasil_abi::{error::Error, io::MountOptions}; -use crate::mem::phys; +use crate::{mem::phys, proc::random}; -pub mod devfs; +// pub mod devfs; pub mod sysfs; /// Describes in-memory filesystem image used as initial root @@ -53,3 +54,16 @@ pub fn create_filesystem(options: &MountOptions) -> Result { _ => todo!(), } } + +/// Adds "pseudo"-devices to the filesystem (i.e. /dev/random) +pub fn add_pseudo_devices() -> Result<(), Error> { + let random = read_fn_node(move |_, buf| { + random::read(buf); + Ok(buf.len()) + }); + + let root = devfs::root(); + root.add_child("random", random)?; + + Ok(()) +} diff --git a/src/init.rs b/src/init.rs index 619de99a..dd41b086 100644 --- a/src/init.rs +++ b/src/init.rs @@ -3,11 +3,12 @@ use abi::{ error::Error, io::{OpenOptions, RawFd}, }; +use kernel_fs::devfs; use memfs::MemoryFilesystem; use vfs::{Action, IoContext, NodeRef}; use crate::{ - fs::{devfs, FileBlockAllocator, INITRD_DATA}, + fs::{FileBlockAllocator, INITRD_DATA}, proc, }; diff --git a/src/main.rs b/src/main.rs index e73e5093..69bafe83 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,7 +39,7 @@ use kernel_util::sync::SpinFence; use crate::{ arch::{ArchitectureImpl, ARCHITECTURE}, - fs::{devfs, sysfs}, + fs::sysfs, mem::heap, proc::random, task::{spawn_kernel_closure, Cpu}, @@ -96,7 +96,7 @@ pub fn kernel_main() -> ! { // Setup the sysfs sysfs::init(); - devfs::add_pseudo_devices().unwrap(); + fs::add_pseudo_devices().unwrap(); unsafe { ARCHITECTURE.start_application_processors();