mem: implement PageBox<T>
This commit is contained in:
parent
4d23cc5c74
commit
6aa18a1fa2
@ -7,3 +7,4 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
|
||||
log = "0.4.20"
|
||||
|
@ -6,9 +6,10 @@ extern "Rust" {
|
||||
pub fn __acquire_irq_guard() -> bool;
|
||||
pub fn __release_irq_guard(mask: bool);
|
||||
|
||||
pub fn __allocate_2m_page() -> u64;
|
||||
pub fn __allocate_page() -> u64;
|
||||
pub fn __free_page(page: u64);
|
||||
pub fn __allocate_2m_page() -> Result<PhysicalAddress, Error>;
|
||||
pub fn __allocate_page() -> Result<PhysicalAddress, Error>;
|
||||
pub fn __allocate_contiguous_pages(count: usize) -> Result<PhysicalAddress, Error>;
|
||||
pub fn __free_page(page: PhysicalAddress);
|
||||
|
||||
pub fn __virtualize(phys: u64) -> usize;
|
||||
pub fn __physicalize(virt: usize) -> u64;
|
||||
|
@ -1,5 +1,12 @@
|
||||
#![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;
|
||||
|
||||
|
@ -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 device;
|
||||
pub mod pointer;
|
||||
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> {}
|
||||
|
@ -1,11 +1,9 @@
|
||||
//! Pointer utilities and interfaces
|
||||
|
||||
use core::{
|
||||
fmt,
|
||||
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
|
||||
#[repr(transparent)]
|
@ -3,13 +3,7 @@
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
#![allow(clippy::new_ret_no_self)]
|
||||
#![deny(missing_docs)]
|
||||
#![feature(
|
||||
trait_upcasting,
|
||||
if_let_guard,
|
||||
maybe_uninit_slice,
|
||||
trait_alias,
|
||||
let_chains
|
||||
)]
|
||||
#![feature(if_let_guard, maybe_uninit_slice, trait_alias, let_chains)]
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate hosted_tests;
|
||||
|
@ -16,7 +16,10 @@ use device_api::{
|
||||
Device,
|
||||
};
|
||||
use kernel_util::{
|
||||
mem::address::{FromRaw, PhysicalAddress},
|
||||
mem::{
|
||||
address::{FromRaw, PhysicalAddress},
|
||||
pointer::PhysicalRef,
|
||||
},
|
||||
sync::IrqSafeSpinlock,
|
||||
util::OneTimeInit,
|
||||
};
|
||||
@ -27,7 +30,7 @@ use crate::{
|
||||
x86_64::{smp::CPU_COUNT, IrqNumber, SHUTDOWN_FENCE},
|
||||
Architecture, CpuMessage, ARCHITECTURE,
|
||||
},
|
||||
mem::{heap::GLOBAL_HEAP, pointer::PhysicalRef, read_memory, write_memory},
|
||||
mem::{heap::GLOBAL_HEAP, read_memory, write_memory},
|
||||
};
|
||||
|
||||
use super::intrinsics;
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! x86-64-specific process address space management functions
|
||||
use kernel_util::mem::{
|
||||
address::{AsPhysicalAddress, IntoRaw, PhysicalAddress},
|
||||
pointer::PhysicalRefMut,
|
||||
table::EntryLevelExt,
|
||||
};
|
||||
use yggdrasil_abi::error::Error;
|
||||
@ -9,7 +10,6 @@ use crate::{
|
||||
arch::x86_64::intrinsics,
|
||||
mem::{
|
||||
phys,
|
||||
pointer::PhysicalRefMut,
|
||||
process::ProcessAddressSpaceManager,
|
||||
table::{EntryLevel, MapAttributes, NextPageTable},
|
||||
},
|
||||
|
@ -6,11 +6,13 @@ use core::{
|
||||
|
||||
use abi::error::Error;
|
||||
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::{
|
||||
phys,
|
||||
pointer::{PhysicalRef, PhysicalRefMut},
|
||||
table::{EntryLevel, MapAttributes, NextPageTable, NonTerminalEntryLevel},
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,10 @@
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
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::{
|
||||
arch::{
|
||||
@ -16,7 +19,7 @@ use crate::{
|
||||
},
|
||||
Architecture, ArchitectureImpl,
|
||||
},
|
||||
mem::{phys, pointer::PhysicalRefMut},
|
||||
mem::phys,
|
||||
task::Cpu,
|
||||
};
|
||||
|
||||
|
@ -20,7 +20,7 @@ impl NvmeDrive {
|
||||
nsid: u32,
|
||||
) -> Result<&'static NvmeDrive, NvmeError> {
|
||||
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 = identify.lba_fmt(current_lba_format_idx).unwrap();
|
||||
@ -49,23 +49,6 @@ impl NvmeDrive {
|
||||
|
||||
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 {
|
||||
|
@ -6,7 +6,7 @@ use alloc::{collections::BTreeMap, vec::Vec};
|
||||
use device_api::{interrupt::MsiHandler, Device};
|
||||
use kernel_util::{
|
||||
mem::{
|
||||
address::{AsPhysicalAddress, FromRaw, IntoRaw, PhysicalAddress},
|
||||
address::{FromRaw, IntoRaw, PhysicalAddress},
|
||||
device::{DeviceMemoryIo, DeviceMemoryIoMut},
|
||||
},
|
||||
sync::IrqSafeSpinlock,
|
||||
@ -32,7 +32,6 @@ use crate::{
|
||||
queue::{CompletionQueueEntry, SubmissionQueueEntry},
|
||||
},
|
||||
},
|
||||
mem::pointer::PhysicalRefMut,
|
||||
task::runtime,
|
||||
};
|
||||
|
||||
@ -117,8 +116,8 @@ register_structs! {
|
||||
|
||||
pub struct NvmeController {
|
||||
regs: IrqSafeSpinlock<DeviceMemoryIo<'static, Regs>>,
|
||||
admin_q: OneTimeInit<QueuePair<'static>>,
|
||||
ioqs: OneTimeInit<Vec<QueuePair<'static>>>,
|
||||
admin_q: OneTimeInit<QueuePair>,
|
||||
ioqs: OneTimeInit<Vec<QueuePair>>,
|
||||
vector_table: IrqSafeSpinlock<DeviceMemoryIoMut<'static, [MsiXEntry]>>,
|
||||
drive_table: IrqSafeSpinlock<BTreeMap<u32, &'static NvmeDrive>>,
|
||||
controller_id: OneTimeInit<usize>,
|
||||
@ -126,6 +125,12 @@ pub struct NvmeController {
|
||||
doorbell_shift: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum IoDirection {
|
||||
Read,
|
||||
Write,
|
||||
}
|
||||
|
||||
impl Regs {
|
||||
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;
|
||||
@ -141,7 +146,7 @@ impl NvmeController {
|
||||
let admin_q = self.admin_q.get();
|
||||
|
||||
// Identify the controller
|
||||
let _identify = admin_q.request(IdentifyControllerRequest)?.await?;
|
||||
let _identify = admin_q.request(IdentifyControllerRequest).await?;
|
||||
|
||||
// TODO do something with identify_controller
|
||||
|
||||
@ -185,7 +190,7 @@ impl NvmeController {
|
||||
let admin_q = self.admin_q.get();
|
||||
|
||||
let namespaces = admin_q
|
||||
.request(IdentifyActiveNamespaceIdListRequest { start_id: 0 })?
|
||||
.request(IdentifyActiveNamespaceIdListRequest { start_id: 0 })
|
||||
.await?;
|
||||
|
||||
let count = namespaces.entries.iter().position(|&x| x == 0).unwrap();
|
||||
@ -205,50 +210,37 @@ impl NvmeController {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn read_block(
|
||||
// TODO sane methods for IO
|
||||
pub async fn perform_io(
|
||||
&'static self,
|
||||
nsid: u32,
|
||||
lba: u64,
|
||||
buffer: &mut PhysicalRefMut<'_, [u8]>,
|
||||
buffer_address: PhysicalAddress,
|
||||
direction: IoDirection,
|
||||
) -> Result<(), NvmeError> {
|
||||
let ioq = &self.ioqs.get()[0];
|
||||
let buffer_address = unsafe { buffer.as_physical_address() };
|
||||
|
||||
debugln!("read nsid={}, lba={:#x}", nsid, lba);
|
||||
let cmd_id = ioq.submit(
|
||||
IoRead {
|
||||
nsid,
|
||||
lba,
|
||||
count: 1,
|
||||
},
|
||||
&[buffer_address],
|
||||
true,
|
||||
);
|
||||
|
||||
ioq.wait_for_completion(cmd_id, ()).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn write_block(
|
||||
&'static self,
|
||||
nsid: u32,
|
||||
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,
|
||||
);
|
||||
debugln!("{:?} nsid={}, lba={:#x}", direction, nsid, lba);
|
||||
let cmd_id = match direction {
|
||||
IoDirection::Read => ioq.submit(
|
||||
IoRead {
|
||||
nsid,
|
||||
lba,
|
||||
count: 1,
|
||||
},
|
||||
&[buffer_address],
|
||||
true,
|
||||
),
|
||||
IoDirection::Write => ioq.submit(
|
||||
IoWrite {
|
||||
nsid,
|
||||
lba,
|
||||
count: 1,
|
||||
},
|
||||
&[buffer_address],
|
||||
true,
|
||||
),
|
||||
};
|
||||
|
||||
ioq.wait_for_completion(cmd_id, ()).await?;
|
||||
|
||||
|
@ -14,18 +14,14 @@ use bytemuck::{Pod, Zeroable};
|
||||
use futures_util::Future;
|
||||
use kernel_util::{
|
||||
mem::{
|
||||
address::{IntoRaw, PhysicalAddress},
|
||||
table::EntryLevelExt,
|
||||
address::{AsPhysicalAddress, IntoRaw, PhysicalAddress},
|
||||
PageBox,
|
||||
},
|
||||
sync::IrqSafeSpinlock,
|
||||
};
|
||||
use static_assertions::const_assert;
|
||||
|
||||
use crate::{
|
||||
arch::L3,
|
||||
mem::{phys, pointer::PhysicalRefMut},
|
||||
task::runtime::QueueWaker,
|
||||
};
|
||||
use crate::task::runtime::QueueWaker;
|
||||
|
||||
use super::{
|
||||
command::{Command, Request},
|
||||
@ -74,9 +70,8 @@ pub struct CompletionQueueEntry {
|
||||
dw: [u32; 4],
|
||||
}
|
||||
|
||||
pub struct Queue<'a, T> {
|
||||
data: PhysicalRefMut<'a, [T]>,
|
||||
|
||||
pub struct Queue<T> {
|
||||
data: PageBox<[T]>,
|
||||
mask: usize,
|
||||
head: usize,
|
||||
tail: usize,
|
||||
@ -86,28 +81,26 @@ pub struct Queue<'a, T> {
|
||||
tail_doorbell: *mut u32,
|
||||
}
|
||||
|
||||
struct Inner<'a> {
|
||||
sq: Queue<'a, SubmissionQueueEntry>,
|
||||
cq: Queue<'a, CompletionQueueEntry>,
|
||||
struct Inner {
|
||||
sq: Queue<SubmissionQueueEntry>,
|
||||
cq: Queue<CompletionQueueEntry>,
|
||||
|
||||
completed: BTreeMap<u32, CompletionQueueEntry>,
|
||||
pending: BTreeSet<u32>,
|
||||
}
|
||||
|
||||
// TODO PageBox<T>?
|
||||
#[allow(unused)]
|
||||
pub struct QueuePair<'a> {
|
||||
base: PhysicalAddress,
|
||||
page_count: usize,
|
||||
pub struct QueuePair {
|
||||
id: u32,
|
||||
|
||||
#[allow(unused)]
|
||||
vector: usize,
|
||||
|
||||
sq_base: PhysicalAddress,
|
||||
cq_base: PhysicalAddress,
|
||||
|
||||
completion_notify: QueueWaker,
|
||||
|
||||
inner: IrqSafeSpinlock<Inner<'a>>,
|
||||
inner: IrqSafeSpinlock<Inner>,
|
||||
}
|
||||
|
||||
const_assert!(size_of::<CompletionQueueEntry>().is_power_of_two());
|
||||
@ -166,25 +159,23 @@ impl CompletionQueueEntry {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Queue<'a, T> {
|
||||
pub unsafe fn from_raw_parts(
|
||||
base: PhysicalAddress,
|
||||
len: usize,
|
||||
impl<T> Queue<T> {
|
||||
pub fn new(
|
||||
data: PageBox<[T]>,
|
||||
head_doorbell: *mut u32,
|
||||
tail_doorbell: *mut u32,
|
||||
phase: bool,
|
||||
) -> Self {
|
||||
// Submission queues have tail doorbells, completion queues have head doorbells
|
||||
assert!(
|
||||
(head_doorbell.is_null() && !tail_doorbell.is_null())
|
||||
|| (!head_doorbell.is_null() && tail_doorbell.is_null())
|
||||
);
|
||||
|
||||
Self {
|
||||
data: PhysicalRefMut::map_slice(base, len),
|
||||
mask: len - 1,
|
||||
mask: data.len() - 1,
|
||||
head: 0,
|
||||
tail: 0,
|
||||
data,
|
||||
head_doorbell,
|
||||
tail_doorbell,
|
||||
phase,
|
||||
@ -246,13 +237,9 @@ impl<'a, T> Queue<'a, T> {
|
||||
|
||||
wrapped
|
||||
}
|
||||
|
||||
// pub fn is_empty(&self) -> bool {
|
||||
// self.head == self.tail
|
||||
// }
|
||||
}
|
||||
|
||||
impl<'a> QueuePair<'a> {
|
||||
impl QueuePair {
|
||||
pub fn new(
|
||||
id: u32,
|
||||
vector: usize,
|
||||
@ -260,24 +247,16 @@ impl<'a> QueuePair<'a> {
|
||||
sq_doorbell: *mut u32,
|
||||
cq_doorbell: *mut u32,
|
||||
) -> Result<Self, Error> {
|
||||
let sq_size = capacity * size_of::<SubmissionQueueEntry>();
|
||||
let cq_size = capacity * size_of::<CompletionQueueEntry>();
|
||||
let sq_data = PageBox::new_slice(SubmissionQueueEntry::zeroed(), capacity)?;
|
||||
let cq_data = PageBox::new_slice(CompletionQueueEntry::zeroed(), capacity)?;
|
||||
|
||||
let page_count = sq_size.page_count::<L3>() + cq_size.page_count::<L3>();
|
||||
let base = phys::alloc_pages_contiguous(page_count)?;
|
||||
let sq_base = unsafe { sq_data.as_physical_address() };
|
||||
let cq_base = unsafe { cq_data.as_physical_address() };
|
||||
|
||||
let sq_base = base;
|
||||
let cq_base = base.add(sq_size.page_align_up::<L3>());
|
||||
debugln!("Allocated queue pair: sq={:p}, cq={:p}", sq_data, cq_data);
|
||||
|
||||
debugln!(
|
||||
"Allocated queue pair: sq={:x?}, cq={:x?} ({} pages)",
|
||||
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 sq = Queue::new(sq_data, null_mut(), sq_doorbell, true);
|
||||
let cq = Queue::new(cq_data, cq_doorbell, null_mut(), true);
|
||||
|
||||
let inner = IrqSafeSpinlock::new(Inner {
|
||||
sq,
|
||||
@ -291,8 +270,6 @@ impl<'a> QueuePair<'a> {
|
||||
|
||||
id,
|
||||
vector,
|
||||
base,
|
||||
page_count,
|
||||
sq_base,
|
||||
cq_base,
|
||||
inner,
|
||||
@ -313,12 +290,9 @@ impl<'a> QueuePair<'a> {
|
||||
&'r self,
|
||||
command_id: u32,
|
||||
result: T,
|
||||
) -> impl Future<Output = Result<T, CommandError>> + 'r
|
||||
where
|
||||
'r: 'a,
|
||||
{
|
||||
) -> impl Future<Output = Result<T, CommandError>> + 'r {
|
||||
struct Fut<'r, R: Unpin + 'r> {
|
||||
this: &'r QueuePair<'r>,
|
||||
this: &'r QueuePair,
|
||||
response: Option<R>,
|
||||
command_id: u32,
|
||||
}
|
||||
@ -386,34 +360,22 @@ impl<'a> QueuePair<'a> {
|
||||
pub fn request_no_data<'r, C: Command>(
|
||||
&'r self,
|
||||
req: C,
|
||||
) -> impl Future<Output = Result<(), CommandError>> + 'r
|
||||
where
|
||||
'r: 'a,
|
||||
{
|
||||
) -> impl Future<Output = Result<(), CommandError>> + 'r {
|
||||
let command_id = self.submit(req, &[], true);
|
||||
self.wait_for_completion(command_id, ())
|
||||
}
|
||||
|
||||
pub fn request<'r, R: Request>(
|
||||
pub async fn request<'r, R: Request>(
|
||||
&'r self,
|
||||
req: R,
|
||||
) -> Result<
|
||||
impl Future<Output = Result<PhysicalRefMut<'r, R::Response>, CommandError>>,
|
||||
NvmeError,
|
||||
>
|
||||
) -> Result<PageBox<R::Response>, NvmeError>
|
||||
where
|
||||
R::Response: 'r,
|
||||
'r: 'a,
|
||||
{
|
||||
assert_ne!(size_of::<R::Response>(), 0);
|
||||
assert!(size_of::<R::Response>() <= 0x1000);
|
||||
|
||||
let page = phys::alloc_page().map_err(NvmeError::MemoryError)?;
|
||||
// TODO PageBox
|
||||
let response = unsafe { PhysicalRefMut::map(page) };
|
||||
|
||||
let command_id = self.submit(req, &[page], true);
|
||||
Ok(self.wait_for_completion(command_id, response))
|
||||
let response = PageBox::new_uninit().map_err(NvmeError::MemoryError)?;
|
||||
let command_id = self.submit(req, &[unsafe { response.as_physical_address() }], true);
|
||||
let result = self.wait_for_completion(command_id, response).await?;
|
||||
Ok(unsafe { result.assume_init() })
|
||||
}
|
||||
|
||||
pub fn process_completions(&self) -> usize {
|
||||
|
@ -14,7 +14,6 @@ use crate::arch::{Architecture, ArchitectureImpl};
|
||||
pub mod address;
|
||||
pub mod heap;
|
||||
pub mod phys;
|
||||
pub mod pointer;
|
||||
pub mod process;
|
||||
pub mod table;
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
//! Physical memory manager implementation
|
||||
use abi::error::Error;
|
||||
use kernel_util::mem::address::{FromRaw, IntoRaw, PhysicalAddress};
|
||||
|
||||
use crate::mem::pointer::PhysicalRefMut;
|
||||
use kernel_util::mem::{
|
||||
address::{FromRaw, IntoRaw, PhysicalAddress},
|
||||
pointer::PhysicalRefMut,
|
||||
};
|
||||
|
||||
pub type BitmapWord = u64;
|
||||
|
||||
|
@ -208,3 +208,13 @@ fn kernel_physical_memory_region() -> PhysicalMemoryRegion {
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -7,16 +7,12 @@ use elf::{
|
||||
segment::ProgramHeader,
|
||||
ElfStream, ParseError,
|
||||
};
|
||||
use kernel_util::mem::pointer::{PhysicalRef, PhysicalRefMut};
|
||||
use vfs::{FileRef, Read, Seek};
|
||||
use yggdrasil_abi::{error::Error, io::SeekFrom};
|
||||
|
||||
use crate::{
|
||||
mem::{
|
||||
phys,
|
||||
pointer::{PhysicalRef, PhysicalRefMut},
|
||||
process::ProcessAddressSpace,
|
||||
table::MapAttributes,
|
||||
},
|
||||
mem::{phys, process::ProcessAddressSpace, table::MapAttributes},
|
||||
task::process::{ProcessImage, ProcessTlsInfo, ProcessTlsLayout},
|
||||
};
|
||||
|
||||
|
@ -9,13 +9,11 @@ use abi::{
|
||||
process::ProgramArgumentInner,
|
||||
};
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
use kernel_util::mem::pointer::PhysicalRefMut;
|
||||
use vfs::{FileRef, IoContext, Read, Seek};
|
||||
|
||||
use crate::{
|
||||
mem::{
|
||||
phys, pointer::PhysicalRefMut, process::ProcessAddressSpace, table::MapAttributes,
|
||||
ForeignPointer,
|
||||
},
|
||||
mem::{phys, process::ProcessAddressSpace, table::MapAttributes, ForeignPointer},
|
||||
proc,
|
||||
task::{
|
||||
context::TaskContextImpl,
|
||||
@ -190,7 +188,9 @@ pub fn load<P: AsRef<Path>>(
|
||||
let count = file.read(&mut head)?;
|
||||
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 mut shebang_args = shebang.split(' ').collect::<Vec<_>>();
|
||||
if shebang_args.is_empty() || shebang_args.len() >= 8 {
|
||||
|
@ -5,12 +5,7 @@ use std::{
|
||||
};
|
||||
|
||||
use bitflags::bitflags;
|
||||
use bytemuck::Zeroable;
|
||||
use elf::{
|
||||
abi::{PF_W, PF_X, PT_LOAD},
|
||||
endian::AnyEndian,
|
||||
ElfStream,
|
||||
};
|
||||
use elf::{abi::PT_LOAD, endian::AnyEndian, ElfStream};
|
||||
use memtables::x86_64::{FixedTables, KERNEL_L3_COUNT};
|
||||
|
||||
use crate::{GenData, GenError};
|
||||
@ -36,7 +31,7 @@ pub struct X8664Builder<F: Seek + Read> {
|
||||
}
|
||||
|
||||
impl PageFlags {
|
||||
fn from_elf(flags: u32) -> Self {
|
||||
fn from_elf(_flags: u32) -> Self {
|
||||
let mut out = Self::empty();
|
||||
// if flags & PF_W != 0 {
|
||||
out |= Self::WRITABLE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user