mem: implement PageBox<T>

This commit is contained in:
Mark Poliakov 2023-12-10 20:54:15 +02:00
parent 4d23cc5c74
commit 6aa18a1fa2
19 changed files with 342 additions and 177 deletions

View File

@ -7,3 +7,4 @@ 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" }
log = "0.4.20"

View File

@ -6,9 +6,10 @@ extern "Rust" {
pub fn __acquire_irq_guard() -> bool; pub fn __acquire_irq_guard() -> bool;
pub fn __release_irq_guard(mask: bool); pub fn __release_irq_guard(mask: bool);
pub fn __allocate_2m_page() -> u64; pub fn __allocate_2m_page() -> Result<PhysicalAddress, Error>;
pub fn __allocate_page() -> u64; pub fn __allocate_page() -> Result<PhysicalAddress, Error>;
pub fn __free_page(page: u64); pub fn __allocate_contiguous_pages(count: usize) -> Result<PhysicalAddress, Error>;
pub fn __free_page(page: PhysicalAddress);
pub fn __virtualize(phys: u64) -> usize; pub fn __virtualize(phys: u64) -> usize;
pub fn __physicalize(virt: usize) -> u64; pub fn __physicalize(virt: usize) -> u64;

View File

@ -1,5 +1,12 @@
#![no_std] #![no_std]
#![feature(maybe_uninit_slice, step_trait, const_trait_impl, effects)] #![feature(
maybe_uninit_slice,
step_trait,
const_trait_impl,
effects,
slice_ptr_get,
strict_provenance
)]
extern crate alloc; extern crate alloc;

View File

@ -1,3 +1,221 @@
use core::{
alloc::Layout,
fmt,
mem::{size_of, MaybeUninit},
ops::{Deref, DerefMut},
};
use yggdrasil_abi::error::Error;
use crate::api::{__allocate_contiguous_pages, __free_page, __physicalize};
use self::address::{AsPhysicalAddress, PhysicalAddress};
pub mod address; pub mod address;
pub mod device; pub mod device;
pub mod pointer;
pub mod table; pub mod table;
pub struct PageBox<T: ?Sized> {
value: *mut T,
page_count: usize,
}
impl<T> PageBox<T> {
#[inline]
fn alloc_slice(count: usize) -> Result<(PhysicalAddress, usize), Error> {
// TODO hardcoded page sizes
let layout = Layout::array::<T>(count).unwrap();
let page_count = (layout.size() + 0xFFF) / 0x1000;
Ok((
unsafe { __allocate_contiguous_pages(page_count) }?,
page_count,
))
}
#[inline]
fn alloc() -> Result<(PhysicalAddress, usize), Error> {
let page_count = (size_of::<T>() + 0xFFF) / 0x1000;
Ok((
unsafe { __allocate_contiguous_pages(page_count) }?,
page_count,
))
}
pub fn new(init: T) -> Result<PageBox<T>, Error> {
let (base, page_count) = Self::alloc()?;
let value = base.virtualize_raw() as *mut T;
unsafe {
value.write(init);
}
let result = PageBox { value, page_count };
result.trace_created();
Ok(result)
}
pub fn new_slice(item: T, count: usize) -> Result<PageBox<[T]>, Error>
where
T: Copy,
{
let (base, page_count) = Self::alloc_slice(count)?;
let base_virt_ptr = base.virtualize_raw() as *mut T;
let value = core::ptr::slice_from_raw_parts_mut(base_virt_ptr, count);
for i in 0..count {
unsafe {
value.get_unchecked_mut(i).write(item);
}
}
let result = PageBox { value, page_count };
result.trace_created();
Ok(result)
}
pub fn new_uninit() -> Result<PageBox<MaybeUninit<T>>, Error> {
let (base, page_count) = PageBox::<MaybeUninit<T>>::alloc()?;
let value = base.virtualize_raw() as *mut MaybeUninit<T>;
let result = PageBox { value, page_count };
result.trace_created();
Ok(result)
}
pub fn new_uninit_slice(count: usize) -> Result<PageBox<[MaybeUninit<T>]>, Error> {
let (base, page_count) = PageBox::<MaybeUninit<T>>::alloc_slice(count)?;
let base_virt_ptr = base.virtualize_raw() as *mut MaybeUninit<T>;
let value = core::ptr::slice_from_raw_parts_mut(base_virt_ptr, count);
let result = PageBox { value, page_count };
result.trace_created();
Ok(result)
}
}
impl<T: ?Sized> PageBox<T> {
#[inline]
pub fn as_ptr(&self) -> *const T {
self.value as _
}
#[inline]
fn trace_created(&self) {
log::trace!(
"Alloc PageBox<{}> @ {:p}, {}",
core::any::type_name::<T>(),
self.value,
self.page_count
);
}
#[inline]
fn trace_dropped(&self) {
log::trace!(
"Free PageBox<{}> @ {:p}, {}",
core::any::type_name::<T>(),
self.value,
self.page_count
);
}
}
impl<T> PageBox<MaybeUninit<T>> {
pub unsafe fn assume_init(self) -> PageBox<T> {
// SAFETY: Memory-safe, as:
// 1. MaybeUninit<T> is transparent
// 2. self.value still points to the same memory and is not deallocated
let page_count = self.page_count;
let value = MaybeUninit::assume_init_mut(&mut *self.value);
// Prevent deallocation of the PageBox with MaybeUninit
core::mem::forget(self);
PageBox { value, page_count }
}
}
impl<T> PageBox<[MaybeUninit<T>]> {
pub unsafe fn assume_init_slice(self) -> PageBox<[T]> {
// SAFETY: Memory-safe, as:
// 1. MaybeUninit<T> is transparent
// 2. self.value still points to the same memory and is not deallocated
let page_count = self.page_count;
let value = MaybeUninit::slice_assume_init_mut(&mut *self.value);
core::mem::forget(self);
PageBox { value, page_count }
}
pub unsafe fn assume_init_slice_ref(&self) -> &[T] {
MaybeUninit::slice_assume_init_ref(self.deref())
}
pub unsafe fn assume_init_slice_mut(&mut self) -> &mut [T] {
MaybeUninit::slice_assume_init_mut(self.deref_mut())
}
}
impl<T: ?Sized> AsPhysicalAddress for PageBox<T> {
#[inline]
unsafe fn as_physical_address(&self) -> PhysicalAddress {
PhysicalAddress(__physicalize(self.value.addr()))
}
}
impl<T: ?Sized> Deref for PageBox<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*self.value }
}
}
impl<T: ?Sized> DerefMut for PageBox<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.value }
}
}
impl<T: ?Sized> Drop for PageBox<T> {
fn drop(&mut self) {
self.trace_dropped();
unsafe {
core::ptr::drop_in_place(self.value);
}
// SAFETY: Safe, pointer obtained through "virtualize"
let base = PhysicalAddress(unsafe { __physicalize(self.value.addr()) });
for i in 0..self.page_count {
// SAFETY: Safe, page allocated only by this PageBox
unsafe {
__free_page(base.add(0x1000 * i));
}
}
}
}
impl<T: ?Sized> fmt::Pointer for PageBox<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.value.fmt(f)
}
}
impl<T: ?Sized + fmt::Debug> fmt::Debug for PageBox<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.deref(), f)
}
}
impl<T: ?Sized + fmt::Display> fmt::Display for PageBox<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.deref(), f)
}
}
unsafe impl<T: ?Sized + Send> Send for PageBox<T> {}
unsafe impl<T: ?Sized + Sync> Sync for PageBox<T> {}

View File

@ -1,11 +1,9 @@
//! Pointer utilities and interfaces
use core::{ use core::{
fmt, fmt,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
}; };
use kernel_util::mem::address::{AsPhysicalAddress, PhysicalAddress}; use super::address::{AsPhysicalAddress, PhysicalAddress};
/// Wrapper for immutably accessing a value at a physical address /// Wrapper for immutably accessing a value at a physical address
#[repr(transparent)] #[repr(transparent)]

View File

@ -3,13 +3,7 @@
#![cfg_attr(not(test), no_std)] #![cfg_attr(not(test), no_std)]
#![allow(clippy::new_ret_no_self)] #![allow(clippy::new_ret_no_self)]
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature( #![feature(if_let_guard, maybe_uninit_slice, trait_alias, let_chains)]
trait_upcasting,
if_let_guard,
maybe_uninit_slice,
trait_alias,
let_chains
)]
#[cfg(test)] #[cfg(test)]
extern crate hosted_tests; extern crate hosted_tests;

View File

@ -16,7 +16,10 @@ use device_api::{
Device, Device,
}; };
use kernel_util::{ use kernel_util::{
mem::address::{FromRaw, PhysicalAddress}, mem::{
address::{FromRaw, PhysicalAddress},
pointer::PhysicalRef,
},
sync::IrqSafeSpinlock, sync::IrqSafeSpinlock,
util::OneTimeInit, util::OneTimeInit,
}; };
@ -27,7 +30,7 @@ use crate::{
x86_64::{smp::CPU_COUNT, IrqNumber, SHUTDOWN_FENCE}, x86_64::{smp::CPU_COUNT, IrqNumber, SHUTDOWN_FENCE},
Architecture, CpuMessage, ARCHITECTURE, Architecture, CpuMessage, ARCHITECTURE,
}, },
mem::{heap::GLOBAL_HEAP, pointer::PhysicalRef, read_memory, write_memory}, mem::{heap::GLOBAL_HEAP, read_memory, write_memory},
}; };
use super::intrinsics; use super::intrinsics;

View File

@ -1,6 +1,7 @@
//! x86-64-specific process address space management functions //! x86-64-specific process address space management functions
use kernel_util::mem::{ use kernel_util::mem::{
address::{AsPhysicalAddress, IntoRaw, PhysicalAddress}, address::{AsPhysicalAddress, IntoRaw, PhysicalAddress},
pointer::PhysicalRefMut,
table::EntryLevelExt, table::EntryLevelExt,
}; };
use yggdrasil_abi::error::Error; use yggdrasil_abi::error::Error;
@ -9,7 +10,6 @@ use crate::{
arch::x86_64::intrinsics, arch::x86_64::intrinsics,
mem::{ mem::{
phys, phys,
pointer::PhysicalRefMut,
process::ProcessAddressSpaceManager, process::ProcessAddressSpaceManager,
table::{EntryLevel, MapAttributes, NextPageTable}, table::{EntryLevel, MapAttributes, NextPageTable},
}, },

View File

@ -6,11 +6,13 @@ use core::{
use abi::error::Error; use abi::error::Error;
use bitflags::bitflags; use bitflags::bitflags;
use kernel_util::mem::address::{AsPhysicalAddress, FromRaw, PhysicalAddress}; use kernel_util::mem::{
address::{AsPhysicalAddress, FromRaw, PhysicalAddress},
pointer::{PhysicalRef, PhysicalRefMut},
};
use crate::mem::{ use crate::mem::{
phys, phys,
pointer::{PhysicalRef, PhysicalRefMut},
table::{EntryLevel, MapAttributes, NextPageTable, NonTerminalEntryLevel}, table::{EntryLevel, MapAttributes, NextPageTable, NonTerminalEntryLevel},
}; };

View File

@ -2,7 +2,10 @@
use core::sync::atomic::{AtomicUsize, Ordering}; use core::sync::atomic::{AtomicUsize, Ordering};
use acpi_lib::platform::{ProcessorInfo, ProcessorState}; use acpi_lib::platform::{ProcessorInfo, ProcessorState};
use kernel_util::mem::address::{AsPhysicalAddress, FromRaw, IntoRaw, PhysicalAddress}; use kernel_util::mem::{
address::{AsPhysicalAddress, FromRaw, IntoRaw, PhysicalAddress},
pointer::PhysicalRefMut,
};
use crate::{ use crate::{
arch::{ arch::{
@ -16,7 +19,7 @@ use crate::{
}, },
Architecture, ArchitectureImpl, Architecture, ArchitectureImpl,
}, },
mem::{phys, pointer::PhysicalRefMut}, mem::phys,
task::Cpu, task::Cpu,
}; };

View File

@ -20,7 +20,7 @@ impl NvmeDrive {
nsid: u32, nsid: u32,
) -> Result<&'static NvmeDrive, NvmeError> { ) -> Result<&'static NvmeDrive, NvmeError> {
let admin_q = controller.admin_q.get(); let admin_q = controller.admin_q.get();
let identify = admin_q.request(IdentifyNamespaceRequest { nsid })?.await?; let identify = admin_q.request(IdentifyNamespaceRequest { nsid }).await?;
let current_lba_format_idx = identify.current_lba_fmt_idx(); let current_lba_format_idx = identify.current_lba_fmt_idx();
let current_lba_format = identify.lba_fmt(current_lba_format_idx).unwrap(); let current_lba_format = identify.lba_fmt(current_lba_format_idx).unwrap();
@ -49,23 +49,6 @@ impl NvmeDrive {
Ok(dev) Ok(dev)
} }
// TODO proper interface for reading/writing blocks
// pub async fn read_block(
// &self,
// lba: u64,
// block: &mut PhysicalRefMut<'_, [u8]>,
// ) -> Result<(), NvmeError> {
// self.controller.read_block(self.nsid, lba, block).await
// }
// pub async fn write_block(
// &self,
// lba: u64,
// block: &PhysicalRefMut<'_, [u8]>,
// ) -> Result<(), NvmeError> {
// self.controller.write_block(self.nsid, lba, block).await
// }
} }
impl BlockDevice for NvmeDrive { impl BlockDevice for NvmeDrive {

View File

@ -6,7 +6,7 @@ use alloc::{collections::BTreeMap, vec::Vec};
use device_api::{interrupt::MsiHandler, Device}; use device_api::{interrupt::MsiHandler, Device};
use kernel_util::{ use kernel_util::{
mem::{ mem::{
address::{AsPhysicalAddress, FromRaw, IntoRaw, PhysicalAddress}, address::{FromRaw, IntoRaw, PhysicalAddress},
device::{DeviceMemoryIo, DeviceMemoryIoMut}, device::{DeviceMemoryIo, DeviceMemoryIoMut},
}, },
sync::IrqSafeSpinlock, sync::IrqSafeSpinlock,
@ -32,7 +32,6 @@ use crate::{
queue::{CompletionQueueEntry, SubmissionQueueEntry}, queue::{CompletionQueueEntry, SubmissionQueueEntry},
}, },
}, },
mem::pointer::PhysicalRefMut,
task::runtime, task::runtime,
}; };
@ -117,8 +116,8 @@ register_structs! {
pub struct NvmeController { pub struct NvmeController {
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>, regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
admin_q: OneTimeInit<QueuePair<'static>>, admin_q: OneTimeInit<QueuePair>,
ioqs: OneTimeInit<Vec<QueuePair<'static>>>, ioqs: OneTimeInit<Vec<QueuePair>>,
vector_table: IrqSafeSpinlock<DeviceMemoryIoMut<'static, [MsiXEntry]>>, vector_table: IrqSafeSpinlock<DeviceMemoryIoMut<'static, [MsiXEntry]>>,
drive_table: IrqSafeSpinlock<BTreeMap<u32, &'static NvmeDrive>>, drive_table: IrqSafeSpinlock<BTreeMap<u32, &'static NvmeDrive>>,
controller_id: OneTimeInit<usize>, controller_id: OneTimeInit<usize>,
@ -126,6 +125,12 @@ pub struct NvmeController {
doorbell_shift: usize, doorbell_shift: usize,
} }
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum IoDirection {
Read,
Write,
}
impl Regs { impl Regs {
unsafe fn doorbell_ptr(&self, shift: usize, completion: bool, queue_index: usize) -> *mut u32 { unsafe fn doorbell_ptr(&self, shift: usize, completion: bool, queue_index: usize) -> *mut u32 {
let doorbell_base = (self as *const Regs as *mut Regs).addr() + 0x1000; let doorbell_base = (self as *const Regs as *mut Regs).addr() + 0x1000;
@ -141,7 +146,7 @@ impl NvmeController {
let admin_q = self.admin_q.get(); let admin_q = self.admin_q.get();
// Identify the controller // Identify the controller
let _identify = admin_q.request(IdentifyControllerRequest)?.await?; let _identify = admin_q.request(IdentifyControllerRequest).await?;
// TODO do something with identify_controller // TODO do something with identify_controller
@ -185,7 +190,7 @@ impl NvmeController {
let admin_q = self.admin_q.get(); let admin_q = self.admin_q.get();
let namespaces = admin_q let namespaces = admin_q
.request(IdentifyActiveNamespaceIdListRequest { start_id: 0 })? .request(IdentifyActiveNamespaceIdListRequest { start_id: 0 })
.await?; .await?;
let count = namespaces.entries.iter().position(|&x| x == 0).unwrap(); let count = namespaces.entries.iter().position(|&x| x == 0).unwrap();
@ -205,50 +210,37 @@ impl NvmeController {
Ok(()) Ok(())
} }
pub async fn read_block( // TODO sane methods for IO
pub async fn perform_io(
&'static self, &'static self,
nsid: u32, nsid: u32,
lba: u64, lba: u64,
buffer: &mut PhysicalRefMut<'_, [u8]>, buffer_address: PhysicalAddress,
direction: IoDirection,
) -> Result<(), NvmeError> { ) -> Result<(), NvmeError> {
let ioq = &self.ioqs.get()[0]; let ioq = &self.ioqs.get()[0];
let buffer_address = unsafe { buffer.as_physical_address() };
debugln!("read nsid={}, lba={:#x}", nsid, lba); debugln!("{:?} nsid={}, lba={:#x}", direction, nsid, lba);
let cmd_id = ioq.submit( let cmd_id = match direction {
IoRead { IoDirection::Read => ioq.submit(
nsid, IoRead {
lba, nsid,
count: 1, lba,
}, count: 1,
&[buffer_address], },
true, &[buffer_address],
); true,
),
ioq.wait_for_completion(cmd_id, ()).await?; IoDirection::Write => ioq.submit(
IoWrite {
Ok(()) nsid,
} lba,
count: 1,
pub async fn write_block( },
&'static self, &[buffer_address],
nsid: u32, true,
lba: u64, ),
buffer: &PhysicalRefMut<'_, [u8]>, };
) -> Result<(), NvmeError> {
let ioq = &self.ioqs.get()[0];
let buffer_address = unsafe { buffer.as_physical_address() };
debugln!("write nsid={}, lba={:#x}", nsid, lba);
let cmd_id = ioq.submit(
IoWrite {
nsid,
lba,
count: 1,
},
&[buffer_address],
true,
);
ioq.wait_for_completion(cmd_id, ()).await?; ioq.wait_for_completion(cmd_id, ()).await?;

View File

@ -14,18 +14,14 @@ use bytemuck::{Pod, Zeroable};
use futures_util::Future; use futures_util::Future;
use kernel_util::{ use kernel_util::{
mem::{ mem::{
address::{IntoRaw, PhysicalAddress}, address::{AsPhysicalAddress, IntoRaw, PhysicalAddress},
table::EntryLevelExt, PageBox,
}, },
sync::IrqSafeSpinlock, sync::IrqSafeSpinlock,
}; };
use static_assertions::const_assert; use static_assertions::const_assert;
use crate::{ use crate::task::runtime::QueueWaker;
arch::L3,
mem::{phys, pointer::PhysicalRefMut},
task::runtime::QueueWaker,
};
use super::{ use super::{
command::{Command, Request}, command::{Command, Request},
@ -74,9 +70,8 @@ pub struct CompletionQueueEntry {
dw: [u32; 4], dw: [u32; 4],
} }
pub struct Queue<'a, T> { pub struct Queue<T> {
data: PhysicalRefMut<'a, [T]>, data: PageBox<[T]>,
mask: usize, mask: usize,
head: usize, head: usize,
tail: usize, tail: usize,
@ -86,28 +81,26 @@ pub struct Queue<'a, T> {
tail_doorbell: *mut u32, tail_doorbell: *mut u32,
} }
struct Inner<'a> { struct Inner {
sq: Queue<'a, SubmissionQueueEntry>, sq: Queue<SubmissionQueueEntry>,
cq: Queue<'a, CompletionQueueEntry>, cq: Queue<CompletionQueueEntry>,
completed: BTreeMap<u32, CompletionQueueEntry>, completed: BTreeMap<u32, CompletionQueueEntry>,
pending: BTreeSet<u32>, pending: BTreeSet<u32>,
} }
// TODO PageBox<T>? pub struct QueuePair {
#[allow(unused)]
pub struct QueuePair<'a> {
base: PhysicalAddress,
page_count: usize,
id: u32, id: u32,
#[allow(unused)]
vector: usize, vector: usize,
sq_base: PhysicalAddress, sq_base: PhysicalAddress,
cq_base: PhysicalAddress, cq_base: PhysicalAddress,
completion_notify: QueueWaker, completion_notify: QueueWaker,
inner: IrqSafeSpinlock<Inner<'a>>, inner: IrqSafeSpinlock<Inner>,
} }
const_assert!(size_of::<CompletionQueueEntry>().is_power_of_two()); const_assert!(size_of::<CompletionQueueEntry>().is_power_of_two());
@ -166,25 +159,23 @@ impl CompletionQueueEntry {
} }
} }
impl<'a, T> Queue<'a, T> { impl<T> Queue<T> {
pub unsafe fn from_raw_parts( pub fn new(
base: PhysicalAddress, data: PageBox<[T]>,
len: usize,
head_doorbell: *mut u32, head_doorbell: *mut u32,
tail_doorbell: *mut u32, tail_doorbell: *mut u32,
phase: bool, phase: bool,
) -> Self { ) -> Self {
// Submission queues have tail doorbells, completion queues have head doorbells
assert!( assert!(
(head_doorbell.is_null() && !tail_doorbell.is_null()) (head_doorbell.is_null() && !tail_doorbell.is_null())
|| (!head_doorbell.is_null() && tail_doorbell.is_null()) || (!head_doorbell.is_null() && tail_doorbell.is_null())
); );
Self { Self {
data: PhysicalRefMut::map_slice(base, len), mask: data.len() - 1,
mask: len - 1,
head: 0, head: 0,
tail: 0, tail: 0,
data,
head_doorbell, head_doorbell,
tail_doorbell, tail_doorbell,
phase, phase,
@ -246,13 +237,9 @@ impl<'a, T> Queue<'a, T> {
wrapped wrapped
} }
// pub fn is_empty(&self) -> bool {
// self.head == self.tail
// }
} }
impl<'a> QueuePair<'a> { impl QueuePair {
pub fn new( pub fn new(
id: u32, id: u32,
vector: usize, vector: usize,
@ -260,24 +247,16 @@ impl<'a> QueuePair<'a> {
sq_doorbell: *mut u32, sq_doorbell: *mut u32,
cq_doorbell: *mut u32, cq_doorbell: *mut u32,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let sq_size = capacity * size_of::<SubmissionQueueEntry>(); let sq_data = PageBox::new_slice(SubmissionQueueEntry::zeroed(), capacity)?;
let cq_size = capacity * size_of::<CompletionQueueEntry>(); let cq_data = PageBox::new_slice(CompletionQueueEntry::zeroed(), capacity)?;
let page_count = sq_size.page_count::<L3>() + cq_size.page_count::<L3>(); let sq_base = unsafe { sq_data.as_physical_address() };
let base = phys::alloc_pages_contiguous(page_count)?; let cq_base = unsafe { cq_data.as_physical_address() };
let sq_base = base; debugln!("Allocated queue pair: sq={:p}, cq={:p}", sq_data, cq_data);
let cq_base = base.add(sq_size.page_align_up::<L3>());
debugln!( let sq = Queue::new(sq_data, null_mut(), sq_doorbell, true);
"Allocated queue pair: sq={:x?}, cq={:x?} ({} pages)", let cq = Queue::new(cq_data, cq_doorbell, null_mut(), true);
sq_base..sq_base.add(sq_size),
cq_base..cq_base.add(cq_size),
page_count
);
let sq = unsafe { Queue::from_raw_parts(sq_base, capacity, null_mut(), sq_doorbell, true) };
let cq = unsafe { Queue::from_raw_parts(cq_base, capacity, cq_doorbell, null_mut(), true) };
let inner = IrqSafeSpinlock::new(Inner { let inner = IrqSafeSpinlock::new(Inner {
sq, sq,
@ -291,8 +270,6 @@ impl<'a> QueuePair<'a> {
id, id,
vector, vector,
base,
page_count,
sq_base, sq_base,
cq_base, cq_base,
inner, inner,
@ -313,12 +290,9 @@ impl<'a> QueuePair<'a> {
&'r self, &'r self,
command_id: u32, command_id: u32,
result: T, result: T,
) -> impl Future<Output = Result<T, CommandError>> + 'r ) -> impl Future<Output = Result<T, CommandError>> + 'r {
where
'r: 'a,
{
struct Fut<'r, R: Unpin + 'r> { struct Fut<'r, R: Unpin + 'r> {
this: &'r QueuePair<'r>, this: &'r QueuePair,
response: Option<R>, response: Option<R>,
command_id: u32, command_id: u32,
} }
@ -386,34 +360,22 @@ impl<'a> QueuePair<'a> {
pub fn request_no_data<'r, C: Command>( pub fn request_no_data<'r, C: Command>(
&'r self, &'r self,
req: C, req: C,
) -> impl Future<Output = Result<(), CommandError>> + 'r ) -> impl Future<Output = Result<(), CommandError>> + 'r {
where
'r: 'a,
{
let command_id = self.submit(req, &[], true); let command_id = self.submit(req, &[], true);
self.wait_for_completion(command_id, ()) self.wait_for_completion(command_id, ())
} }
pub fn request<'r, R: Request>( pub async fn request<'r, R: Request>(
&'r self, &'r self,
req: R, req: R,
) -> Result< ) -> Result<PageBox<R::Response>, NvmeError>
impl Future<Output = Result<PhysicalRefMut<'r, R::Response>, CommandError>>,
NvmeError,
>
where where
R::Response: 'r, R::Response: 'r,
'r: 'a,
{ {
assert_ne!(size_of::<R::Response>(), 0); let response = PageBox::new_uninit().map_err(NvmeError::MemoryError)?;
assert!(size_of::<R::Response>() <= 0x1000); let command_id = self.submit(req, &[unsafe { response.as_physical_address() }], true);
let result = self.wait_for_completion(command_id, response).await?;
let page = phys::alloc_page().map_err(NvmeError::MemoryError)?; Ok(unsafe { result.assume_init() })
// TODO PageBox
let response = unsafe { PhysicalRefMut::map(page) };
let command_id = self.submit(req, &[page], true);
Ok(self.wait_for_completion(command_id, response))
} }
pub fn process_completions(&self) -> usize { pub fn process_completions(&self) -> usize {

View File

@ -14,7 +14,6 @@ use crate::arch::{Architecture, ArchitectureImpl};
pub mod address; pub mod address;
pub mod heap; pub mod heap;
pub mod phys; pub mod phys;
pub mod pointer;
pub mod process; pub mod process;
pub mod table; pub mod table;

View File

@ -1,8 +1,9 @@
//! Physical memory manager implementation //! Physical memory manager implementation
use abi::error::Error; use abi::error::Error;
use kernel_util::mem::address::{FromRaw, IntoRaw, PhysicalAddress}; use kernel_util::mem::{
address::{FromRaw, IntoRaw, PhysicalAddress},
use crate::mem::pointer::PhysicalRefMut; pointer::PhysicalRefMut,
};
pub type BitmapWord = u64; pub type BitmapWord = u64;

View File

@ -208,3 +208,13 @@ fn kernel_physical_memory_region() -> PhysicalMemoryRegion {
PhysicalMemoryRegion { base, size } PhysicalMemoryRegion { base, size }
} }
#[no_mangle]
fn __allocate_contiguous_pages(count: usize) -> Result<PhysicalAddress, Error> {
alloc_pages_contiguous(count)
}
#[no_mangle]
unsafe fn __free_page(page: PhysicalAddress) {
free_page(page)
}

View File

@ -7,16 +7,12 @@ use elf::{
segment::ProgramHeader, segment::ProgramHeader,
ElfStream, ParseError, ElfStream, ParseError,
}; };
use kernel_util::mem::pointer::{PhysicalRef, PhysicalRefMut};
use vfs::{FileRef, Read, Seek}; use vfs::{FileRef, Read, Seek};
use yggdrasil_abi::{error::Error, io::SeekFrom}; use yggdrasil_abi::{error::Error, io::SeekFrom};
use crate::{ use crate::{
mem::{ mem::{phys, process::ProcessAddressSpace, table::MapAttributes},
phys,
pointer::{PhysicalRef, PhysicalRefMut},
process::ProcessAddressSpace,
table::MapAttributes,
},
task::process::{ProcessImage, ProcessTlsInfo, ProcessTlsLayout}, task::process::{ProcessImage, ProcessTlsInfo, ProcessTlsLayout},
}; };

View File

@ -9,13 +9,11 @@ use abi::{
process::ProgramArgumentInner, process::ProgramArgumentInner,
}; };
use alloc::{string::String, sync::Arc, vec::Vec}; use alloc::{string::String, sync::Arc, vec::Vec};
use kernel_util::mem::pointer::PhysicalRefMut;
use vfs::{FileRef, IoContext, Read, Seek}; use vfs::{FileRef, IoContext, Read, Seek};
use crate::{ use crate::{
mem::{ mem::{phys, process::ProcessAddressSpace, table::MapAttributes, ForeignPointer},
phys, pointer::PhysicalRefMut, process::ProcessAddressSpace, table::MapAttributes,
ForeignPointer,
},
proc, proc,
task::{ task::{
context::TaskContextImpl, context::TaskContextImpl,
@ -190,7 +188,9 @@ pub fn load<P: AsRef<Path>>(
let count = file.read(&mut head)?; let count = file.read(&mut head)?;
let head = &head[..count]; let head = &head[..count];
if let Some(shebang) = head.strip_prefix(b"#!") && let Some((shebang, _)) = shebang.split_once(|&ch| ch == b'\n') { if let Some(shebang) = head.strip_prefix(b"#!")
&& let Some((shebang, _)) = shebang.split_once(|&ch| ch == b'\n')
{
let shebang = core::str::from_utf8(shebang).map_err(|_| Error::InvalidFile)?; let shebang = core::str::from_utf8(shebang).map_err(|_| Error::InvalidFile)?;
let mut shebang_args = shebang.split(' ').collect::<Vec<_>>(); let mut shebang_args = shebang.split(' ').collect::<Vec<_>>();
if shebang_args.is_empty() || shebang_args.len() >= 8 { if shebang_args.is_empty() || shebang_args.len() >= 8 {

View File

@ -5,12 +5,7 @@ use std::{
}; };
use bitflags::bitflags; use bitflags::bitflags;
use bytemuck::Zeroable; use elf::{abi::PT_LOAD, endian::AnyEndian, ElfStream};
use elf::{
abi::{PF_W, PF_X, PT_LOAD},
endian::AnyEndian,
ElfStream,
};
use memtables::x86_64::{FixedTables, KERNEL_L3_COUNT}; use memtables::x86_64::{FixedTables, KERNEL_L3_COUNT};
use crate::{GenData, GenError}; use crate::{GenData, GenError};
@ -36,7 +31,7 @@ pub struct X8664Builder<F: Seek + Read> {
} }
impl PageFlags { impl PageFlags {
fn from_elf(flags: u32) -> Self { fn from_elf(_flags: u32) -> Self {
let mut out = Self::empty(); let mut out = Self::empty();
// if flags & PF_W != 0 { // if flags & PF_W != 0 {
out |= Self::WRITABLE; out |= Self::WRITABLE;