block/nvme: move nvme driver to its own crate

This commit is contained in:
Mark Poliakov 2023-12-10 23:22:21 +02:00
parent e78784d96d
commit 8b7a7b9295
20 changed files with 112 additions and 61 deletions

View File

@ -11,6 +11,7 @@ opt-level = 3
[dependencies] [dependencies]
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
vfs = { path = "lib/vfs" } vfs = { path = "lib/vfs" }
# TODO move to drivers
memfs = { path = "lib/memfs" } memfs = { path = "lib/memfs" }
device-api = { path = "lib/device-api", features = ["derive"] } device-api = { path = "lib/device-api", features = ["derive"] }
kernel-util = { path = "lib/kernel-util" } kernel-util = { path = "lib/kernel-util" }
@ -20,6 +21,8 @@ device-api-macros = { path = "lib/device-api/macros" }
# Drivers # Drivers
ygg_driver_pci = { path = "driver/bus/pci" } 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" atomic_enum = "0.2.0"
bitflags = "2.3.3" bitflags = "2.3.3"

View File

@ -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"] }

View File

@ -5,7 +5,7 @@ use core::fmt::{self, Write};
use kernel_util::mem::address::PhysicalAddress; use kernel_util::mem::address::PhysicalAddress;
use tock_registers::{interfaces::Readable, register_structs, registers::ReadOnly, UIntLike}; use tock_registers::{interfaces::Readable, register_structs, registers::ReadOnly, UIntLike};
use crate::device::nvme::queue::PhysicalRegionPage; use crate::queue::PhysicalRegionPage;
use super::queue::SubmissionQueueEntry; use super::queue::SubmissionQueueEntry;

View File

@ -1,8 +1,9 @@
use abi::{error::Error, io::DeviceRequest};
use alloc::{boxed::Box, format}; use alloc::{boxed::Box, format};
use kernel_fs::devfs;
use vfs::BlockDevice; 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}; use super::{error::NvmeError, NvmeController};
@ -27,7 +28,7 @@ impl NvmeDrive {
let lba_size = current_lba_format.lba_data_size().unwrap(); let lba_size = current_lba_format.lba_data_size().unwrap();
let total_lba_count = identify.total_lba_count(); let total_lba_count = identify.total_lba_count();
debugln!( log::debug!(
"ns = {}, lba = {}B, size = {}M", "ns = {}, lba = {}B, size = {}M",
nsid, nsid,
lba_size, lba_size,
@ -41,7 +42,6 @@ impl NvmeDrive {
lba_size, lba_size,
})); }));
// TODO add the drive as a block device
let node_name = format!("nvme{}n{}", controller.controller_id.get(), nsid); let node_name = format!("nvme{}n{}", controller.controller_id.get(), nsid);
devfs::add_named_block_device(dev, node_name).ok(); devfs::add_named_block_device(dev, node_name).ok();

View File

@ -1,4 +1,4 @@
use abi::error::Error; use yggdrasil_abi::error::Error;
use super::queue::CommandError; use super::queue::CommandError;

View File

@ -1,15 +1,21 @@
#![feature(strict_provenance, const_trait_impl)]
#![allow(missing_docs)] #![allow(missing_docs)]
#![no_std]
extern crate alloc;
use core::{mem::size_of, time::Duration}; use core::{mem::size_of, time::Duration};
use abi::error::Error;
use alloc::{boxed::Box, collections::BTreeMap, vec::Vec}; use alloc::{boxed::Box, collections::BTreeMap, vec::Vec};
use command::{IdentifyActiveNamespaceIdListRequest, IdentifyControllerRequest};
use device_api::{interrupt::MsiHandler, Device}; use device_api::{interrupt::MsiHandler, Device};
use drive::NvmeDrive;
use kernel_util::{ use kernel_util::{
mem::{ mem::{
address::{FromRaw, IntoRaw, PhysicalAddress}, address::{FromRaw, IntoRaw, PhysicalAddress},
device::{DeviceMemoryIo, DeviceMemoryIoMut}, device::{DeviceMemoryIo, DeviceMemoryIoMut},
}, },
runtime, message_interrupt_controller, runtime,
sync::IrqSafeSpinlock, sync::IrqSafeSpinlock,
util::OneTimeInit, util::OneTimeInit,
}; };
@ -22,16 +28,11 @@ use ygg_driver_pci::{
capability::{MsiXCapability, MsiXEntry}, capability::{MsiXCapability, MsiXEntry},
PciBaseAddress, PciCommandRegister, PciConfigurationSpace, PciDeviceInfo, PciBaseAddress, PciCommandRegister, PciConfigurationSpace, PciDeviceInfo,
}; };
use yggdrasil_abi::error::Error;
use crate::{ use crate::{
arch::{Architecture, ARCHITECTURE}, command::{IoRead, IoWrite},
device::nvme::{ queue::{CompletionQueueEntry, SubmissionQueueEntry},
command::{
IdentifyActiveNamespaceIdListRequest, IdentifyControllerRequest, IoRead, IoWrite,
},
drive::NvmeDrive,
queue::{CompletionQueueEntry, SubmissionQueueEntry},
},
}; };
use self::{ use self::{
@ -199,7 +200,7 @@ impl NvmeController {
self.drive_table.lock().insert(nsid, drive); self.drive_table.lock().insert(nsid, drive);
} }
Err(error) => { 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> { ) -> Result<(), NvmeError> {
let ioq = &self.ioqs.get()[0]; 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 { let cmd_id = match direction {
IoDirection::Read => ioq.submit( IoDirection::Read => ioq.submit(
IoRead { IoRead {
@ -276,7 +277,7 @@ impl Device for NvmeController {
} }
let timeout = Duration::from_millis(regs.CAP.read(CAP::TO) * 500); 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) { while regs.CSTS.matches_any(CSTS::RDY::SET) {
core::hint::spin_loop(); core::hint::spin_loop();
@ -293,7 +294,7 @@ impl Device for NvmeController {
// Setup the admin queue (index 0) // Setup the admin queue (index 0)
let admin_sq_doorbell = unsafe { regs.doorbell_ptr(self.doorbell_shift, false, 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) }; 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( let admin_q = QueuePair::new(
0, 0,
0, 0,
@ -322,7 +323,7 @@ impl Device for NvmeController {
// Enable the controller // Enable the controller
regs.CC.modify(CC::ENABLE::SET); 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) { while !regs.CSTS.matches_any(CSTS::RDY::SET + CSTS::CFS::SET) {
core::hint::spin_loop(); core::hint::spin_loop();
@ -340,7 +341,7 @@ impl Device for NvmeController {
// Register vector 0 // Register vector 0
vt[0] vt[0]
.register(ARCHITECTURE.message_interrupt_controller(), self) .register(message_interrupt_controller(), self)
.unwrap(); .unwrap();
} }

View File

@ -5,7 +5,6 @@ use core::{
task::{Context, Poll}, task::{Context, Poll},
}; };
use abi::error::Error;
use alloc::{ use alloc::{
collections::{BTreeMap, BTreeSet}, collections::{BTreeMap, BTreeSet},
vec::Vec, vec::Vec,
@ -21,6 +20,7 @@ use kernel_util::{
sync::IrqSafeSpinlock, sync::IrqSafeSpinlock,
}; };
use static_assertions::const_assert; use static_assertions::const_assert;
use yggdrasil_abi::error::Error;
use super::{ use super::{
command::{Command, Request}, command::{Command, Request},
@ -252,7 +252,7 @@ impl QueuePair {
let sq_base = unsafe { sq_data.as_physical_address() }; let sq_base = unsafe { sq_data.as_physical_address() };
let cq_base = unsafe { cq_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 sq = Queue::new(sq_data, null_mut(), sq_doorbell, true);
let cq = Queue::new(cq_data, cq_doorbell, null_mut(), true); let cq = Queue::new(cq_data, cq_doorbell, null_mut(), true);

View File

@ -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"

View File

@ -1,15 +1,10 @@
//! Device virtual file system //! Device virtual file system
use core::sync::atomic::{AtomicUsize, Ordering}; use core::sync::atomic::{AtomicUsize, Ordering};
use abi::error::Error;
use alloc::{format, string::String}; use alloc::{format, string::String};
use kernel_util::util::OneTimeInit; use kernel_util::util::OneTimeInit;
use vfs::{ use vfs::{impls::MemoryDirectory, BlockDevice, CharDevice, Node, NodeFlags, NodeRef};
impls::{read_fn_node, MemoryDirectory}, use yggdrasil_abi::error::Error;
BlockDevice, CharDevice, Node, NodeFlags, NodeRef,
};
use crate::proc::random;
/// Describes the kind of a character device /// Describes the kind of a character device
#[derive(Debug)] #[derive(Debug)]
@ -39,7 +34,7 @@ pub fn root() -> &'static NodeRef {
/// Adds a character device with a custom name /// Adds a character device with a custom name
pub fn add_named_char_device(dev: &'static dyn CharDevice, name: String) -> Result<(), Error> { 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); let node = Node::char(dev, NodeFlags::IN_MEMORY_PROPS);
@ -52,7 +47,7 @@ pub fn add_named_block_device<S: Into<String>>(
name: S, name: S,
) -> Result<(), Error> { ) -> Result<(), Error> {
let name = name.into(); let name = name.into();
infoln!("Add block device: {}", name); log::info!("Add block device: {}", name);
let node = Node::block(dev, NodeFlags::IN_MEMORY_PROPS); 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) 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(())
}

View File

@ -0,0 +1,5 @@
#![no_std]
extern crate alloc;
pub mod devfs;

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
device-api = { path = "../device-api", features = ["derive"] }
log = "0.4.20" log = "0.4.20"
futures-util = { version = "0.3.28", default-features = false, features = ["alloc", "async-await"] } futures-util = { version = "0.3.28", default-features = false, features = ["alloc", "async-await"] }

View File

@ -1,6 +1,7 @@
use core::time::Duration; use core::time::Duration;
use alloc::{string::String, sync::Arc}; use alloc::{string::String, sync::Arc};
use device_api::interrupt::MessageInterruptController;
use yggdrasil_abi::{error::Error, process::ExitCode}; use yggdrasil_abi::{error::Error, process::ExitCode};
use crate::{ use crate::{
@ -39,4 +40,6 @@ extern "Rust" {
pub fn __exit_current(t: &CurrentThread, code: ExitCode) -> !; pub fn __exit_current(t: &CurrentThread, code: ExitCode) -> !;
pub fn __monotonic_timestamp() -> Result<Duration, Error>; pub fn __monotonic_timestamp() -> Result<Duration, Error>;
pub fn __message_interrupt_controller() -> &'static dyn MessageInterruptController;
} }

View File

@ -10,6 +10,8 @@
let_chains let_chains
)] )]
use device_api::interrupt::MessageInterruptController;
extern crate alloc; extern crate alloc;
pub(crate) mod api; pub(crate) mod api;
@ -20,6 +22,11 @@ pub mod sync;
pub mod thread; pub mod thread;
pub mod util; pub mod util;
#[inline]
pub fn message_interrupt_controller() -> &'static dyn MessageInterruptController {
unsafe { api::__message_interrupt_controller() }
}
#[repr(C)] #[repr(C)]
pub struct AlignedTo<Align, Bytes: ?Sized> { pub struct AlignedTo<Align, Bytes: ?Sized> {
pub align: [Align; 0], pub align: [Align; 0],

View File

@ -271,3 +271,8 @@ fn __unmap_device_pages(mapping: &RawDeviceMemoryMapping) {
fn __monotonic_timestamp() -> Result<Duration, Error> { fn __monotonic_timestamp() -> Result<Duration, Error> {
ARCHITECTURE.monotonic_timer().monotonic_timestamp() ARCHITECTURE.monotonic_timer().monotonic_timestamp()
} }
#[no_mangle]
fn __message_interrupt_controller() -> &'static dyn MessageInterruptController {
ARCHITECTURE.message_interrupt_controller()
}

View File

@ -1,6 +1,7 @@
//! x86-64 boot and entry functions //! x86-64 boot and entry functions
use core::{arch::global_asm, sync::atomic::Ordering}; use core::{arch::global_asm, sync::atomic::Ordering};
use kernel_fs::devfs;
use kernel_util::runtime; use kernel_util::runtime;
use tock_registers::interfaces::Writeable; use tock_registers::interfaces::Writeable;
use yboot_proto::{ use yboot_proto::{
@ -10,7 +11,6 @@ use yboot_proto::{
use crate::{ use crate::{
arch::x86_64::{registers::MSR_IA32_KERNEL_GS_BASE, smp::CPU_COUNT}, arch::x86_64::{registers::MSR_IA32_KERNEL_GS_BASE, smp::CPU_COUNT},
fs::devfs,
kernel_main, kernel_secondary_main, kernel_main, kernel_secondary_main,
mem::KERNEL_VIRT_OFFSET, mem::KERNEL_VIRT_OFFSET,
}; };

View File

@ -11,6 +11,7 @@ use device_api::{
Device, Device,
}; };
use git_version::git_version; use git_version::git_version;
use kernel_fs::devfs::{self, CharDeviceType};
use kernel_util::{ use kernel_util::{
mem::{ mem::{
address::{FromRaw, IntoRaw, PhysicalAddress}, address::{FromRaw, IntoRaw, PhysicalAddress},
@ -51,13 +52,9 @@ use crate::{
device::{ device::{
self, self,
display::{console, fb_console::FramebufferConsole, linear_fb::LinearFramebuffer}, display::{console, fb_console::FramebufferConsole, linear_fb::LinearFramebuffer},
nvme,
tty::CombinedTerminal, tty::CombinedTerminal,
}, },
fs::{ fs::{Initrd, INITRD_DATA},
devfs::{self, CharDeviceType},
Initrd, INITRD_DATA,
},
mem::{ mem::{
heap, heap,
phys::{self, reserved::reserve_region, PhysicalMemoryRegion}, phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
@ -392,7 +389,7 @@ impl X86_64 {
0x01, 0x01,
Some(0x08), Some(0x08),
Some(0x02), Some(0x02),
nvme::probe, ygg_driver_nvme::probe,
); );
match self.boot_data.get() { match self.boot_data.get() {

View File

@ -10,8 +10,6 @@ pub mod devtree;
#[cfg(not(target_arch = "aarch64"))] #[cfg(not(target_arch = "aarch64"))]
pub mod bus; pub mod bus;
pub mod nvme;
pub mod display; pub mod display;
pub mod power; pub mod power;
pub mod serial; pub mod serial;

View File

@ -2,14 +2,15 @@
use core::ptr::NonNull; use core::ptr::NonNull;
use kernel_fs::devfs;
use kernel_util::{mem::address::PhysicalAddress, util::OneTimeInit}; use kernel_util::{mem::address::PhysicalAddress, util::OneTimeInit};
use memfs::block::{self, BlockAllocator}; use memfs::block::{self, BlockAllocator};
use vfs::NodeRef; use vfs::{impls::read_fn_node, NodeRef};
use yggdrasil_abi::{error::Error, io::MountOptions}; 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; pub mod sysfs;
/// Describes in-memory filesystem image used as initial root /// Describes in-memory filesystem image used as initial root
@ -53,3 +54,16 @@ pub fn create_filesystem(options: &MountOptions) -> Result<NodeRef, Error> {
_ => todo!(), _ => 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(())
}

View File

@ -3,11 +3,12 @@ use abi::{
error::Error, error::Error,
io::{OpenOptions, RawFd}, io::{OpenOptions, RawFd},
}; };
use kernel_fs::devfs;
use memfs::MemoryFilesystem; use memfs::MemoryFilesystem;
use vfs::{Action, IoContext, NodeRef}; use vfs::{Action, IoContext, NodeRef};
use crate::{ use crate::{
fs::{devfs, FileBlockAllocator, INITRD_DATA}, fs::{FileBlockAllocator, INITRD_DATA},
proc, proc,
}; };

View File

@ -39,7 +39,7 @@ use kernel_util::sync::SpinFence;
use crate::{ use crate::{
arch::{ArchitectureImpl, ARCHITECTURE}, arch::{ArchitectureImpl, ARCHITECTURE},
fs::{devfs, sysfs}, fs::sysfs,
mem::heap, mem::heap,
proc::random, proc::random,
task::{spawn_kernel_closure, Cpu}, task::{spawn_kernel_closure, Cpu},
@ -96,7 +96,7 @@ pub fn kernel_main() -> ! {
// Setup the sysfs // Setup the sysfs
sysfs::init(); sysfs::init();
devfs::add_pseudo_devices().unwrap(); fs::add_pseudo_devices().unwrap();
unsafe { unsafe {
ARCHITECTURE.start_application_processors(); ARCHITECTURE.start_application_processors();