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

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 tock_registers::{interfaces::Readable, register_structs, registers::ReadOnly, UIntLike};
use crate::device::nvme::queue::PhysicalRegionPage;
use crate::queue::PhysicalRegionPage;
use super::queue::SubmissionQueueEntry;

View File

@ -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();

View File

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

View File

@ -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();
}

View File

@ -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);

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
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<S: Into<String>>(
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(())
}

View File

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

View File

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

View File

@ -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<Duration, Error>;
pub fn __message_interrupt_controller() -> &'static dyn MessageInterruptController;
}

View File

@ -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<Align, Bytes: ?Sized> {
pub align: [Align; 0],

View File

@ -271,3 +271,8 @@ fn __unmap_device_pages(mapping: &RawDeviceMemoryMapping) {
fn __monotonic_timestamp() -> Result<Duration, Error> {
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
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,
};

View File

@ -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() {

View File

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

View File

@ -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<NodeRef, Error> {
_ => 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,
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,
};

View File

@ -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();