From 6aa18a1fa202768f6ce366778e1bd2a4bc410571 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Sun, 10 Dec 2023 20:54:15 +0200 Subject: [PATCH] mem: implement PageBox --- lib/kernel-util/Cargo.toml | 1 + lib/kernel-util/src/api.rs | 7 +- lib/kernel-util/src/lib.rs | 9 +- lib/kernel-util/src/mem/mod.rs | 218 ++++++++++++++++++++ {src => lib/kernel-util/src}/mem/pointer.rs | 4 +- lib/vfs/src/lib.rs | 8 +- src/arch/x86_64/acpi.rs | 7 +- src/arch/x86_64/mem/process.rs | 2 +- src/arch/x86_64/mem/table.rs | 6 +- src/arch/x86_64/smp.rs | 7 +- src/device/nvme/drive.rs | 19 +- src/device/nvme/mod.rs | 80 ++++--- src/device/nvme/queue.rs | 106 +++------- src/mem/mod.rs | 1 - src/mem/phys/manager.rs | 7 +- src/mem/phys/mod.rs | 10 + src/proc/elf.rs | 8 +- src/proc/exec.rs | 10 +- tools/gentables/src/x86_64.rs | 9 +- 19 files changed, 342 insertions(+), 177 deletions(-) rename {src => lib/kernel-util/src}/mem/pointer.rs (97%) diff --git a/lib/kernel-util/Cargo.toml b/lib/kernel-util/Cargo.toml index 98dee9e8..81ac1c42 100644 --- a/lib/kernel-util/Cargo.toml +++ b/lib/kernel-util/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" [dependencies] yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } +log = "0.4.20" diff --git a/lib/kernel-util/src/api.rs b/lib/kernel-util/src/api.rs index 99aded18..aa43441f 100644 --- a/lib/kernel-util/src/api.rs +++ b/lib/kernel-util/src/api.rs @@ -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; + pub fn __allocate_page() -> Result; + pub fn __allocate_contiguous_pages(count: usize) -> Result; + pub fn __free_page(page: PhysicalAddress); pub fn __virtualize(phys: u64) -> usize; pub fn __physicalize(virt: usize) -> u64; diff --git a/lib/kernel-util/src/lib.rs b/lib/kernel-util/src/lib.rs index 7a71340a..7f83491a 100644 --- a/lib/kernel-util/src/lib.rs +++ b/lib/kernel-util/src/lib.rs @@ -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; diff --git a/lib/kernel-util/src/mem/mod.rs b/lib/kernel-util/src/mem/mod.rs index 81f4df8c..3140f216 100644 --- a/lib/kernel-util/src/mem/mod.rs +++ b/lib/kernel-util/src/mem/mod.rs @@ -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 { + value: *mut T, + page_count: usize, +} + +impl PageBox { + #[inline] + fn alloc_slice(count: usize) -> Result<(PhysicalAddress, usize), Error> { + // TODO hardcoded page sizes + let layout = Layout::array::(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::() + 0xFFF) / 0x1000; + Ok(( + unsafe { __allocate_contiguous_pages(page_count) }?, + page_count, + )) + } + + pub fn new(init: T) -> Result, 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, 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>, Error> { + let (base, page_count) = PageBox::>::alloc()?; + let value = base.virtualize_raw() as *mut MaybeUninit; + let result = PageBox { value, page_count }; + result.trace_created(); + Ok(result) + } + + pub fn new_uninit_slice(count: usize) -> Result]>, Error> { + let (base, page_count) = PageBox::>::alloc_slice(count)?; + let base_virt_ptr = base.virtualize_raw() as *mut MaybeUninit; + 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 PageBox { + #[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::(), + self.value, + self.page_count + ); + } + + #[inline] + fn trace_dropped(&self) { + log::trace!( + "Free PageBox<{}> @ {:p}, {}", + core::any::type_name::(), + self.value, + self.page_count + ); + } +} + +impl PageBox> { + pub unsafe fn assume_init(self) -> PageBox { + // SAFETY: Memory-safe, as: + // 1. MaybeUninit 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 PageBox<[MaybeUninit]> { + pub unsafe fn assume_init_slice(self) -> PageBox<[T]> { + // SAFETY: Memory-safe, as: + // 1. MaybeUninit 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 AsPhysicalAddress for PageBox { + #[inline] + unsafe fn as_physical_address(&self) -> PhysicalAddress { + PhysicalAddress(__physicalize(self.value.addr())) + } +} + +impl Deref for PageBox { + type Target = T; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + unsafe { &*self.value } + } +} + +impl DerefMut for PageBox { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *self.value } + } +} + +impl Drop for PageBox { + 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 fmt::Pointer for PageBox { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.value.fmt(f) + } +} + +impl fmt::Debug for PageBox { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.deref(), f) + } +} + +impl fmt::Display for PageBox { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.deref(), f) + } +} + +unsafe impl Send for PageBox {} +unsafe impl Sync for PageBox {} diff --git a/src/mem/pointer.rs b/lib/kernel-util/src/mem/pointer.rs similarity index 97% rename from src/mem/pointer.rs rename to lib/kernel-util/src/mem/pointer.rs index 3d3bc55e..db89f6df 100644 --- a/src/mem/pointer.rs +++ b/lib/kernel-util/src/mem/pointer.rs @@ -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)] diff --git a/lib/vfs/src/lib.rs b/lib/vfs/src/lib.rs index 33704419..7b265746 100644 --- a/lib/vfs/src/lib.rs +++ b/lib/vfs/src/lib.rs @@ -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; diff --git a/src/arch/x86_64/acpi.rs b/src/arch/x86_64/acpi.rs index 68c23fe2..e0d2ef95 100644 --- a/src/arch/x86_64/acpi.rs +++ b/src/arch/x86_64/acpi.rs @@ -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; diff --git a/src/arch/x86_64/mem/process.rs b/src/arch/x86_64/mem/process.rs index 71119e90..aba47e2e 100644 --- a/src/arch/x86_64/mem/process.rs +++ b/src/arch/x86_64/mem/process.rs @@ -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}, }, diff --git a/src/arch/x86_64/mem/table.rs b/src/arch/x86_64/mem/table.rs index 884caef2..f6db3d8d 100644 --- a/src/arch/x86_64/mem/table.rs +++ b/src/arch/x86_64/mem/table.rs @@ -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}, }; diff --git a/src/arch/x86_64/smp.rs b/src/arch/x86_64/smp.rs index 11ccfd99..fa69e85f 100644 --- a/src/arch/x86_64/smp.rs +++ b/src/arch/x86_64/smp.rs @@ -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, }; diff --git a/src/device/nvme/drive.rs b/src/device/nvme/drive.rs index 4914c8a9..be2daf60 100644 --- a/src/device/nvme/drive.rs +++ b/src/device/nvme/drive.rs @@ -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 { diff --git a/src/device/nvme/mod.rs b/src/device/nvme/mod.rs index 73447a92..fa705501 100644 --- a/src/device/nvme/mod.rs +++ b/src/device/nvme/mod.rs @@ -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>, - admin_q: OneTimeInit>, - ioqs: OneTimeInit>>, + admin_q: OneTimeInit, + ioqs: OneTimeInit>, vector_table: IrqSafeSpinlock>, drive_table: IrqSafeSpinlock>, controller_id: OneTimeInit, @@ -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?; diff --git a/src/device/nvme/queue.rs b/src/device/nvme/queue.rs index 925da5bd..3d027954 100644 --- a/src/device/nvme/queue.rs +++ b/src/device/nvme/queue.rs @@ -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 { + 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, + cq: Queue, completed: BTreeMap, pending: BTreeSet, } -// TODO PageBox? -#[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: IrqSafeSpinlock, } const_assert!(size_of::().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 Queue { + 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 { - let sq_size = capacity * size_of::(); - let cq_size = capacity * size_of::(); + 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::() + cq_size.page_count::(); - 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::()); + 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> + 'r - where - 'r: 'a, - { + ) -> impl Future> + 'r { struct Fut<'r, R: Unpin + 'r> { - this: &'r QueuePair<'r>, + this: &'r QueuePair, response: Option, 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> + 'r - where - 'r: 'a, - { + ) -> impl Future> + '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, CommandError>>, - NvmeError, - > + ) -> Result, NvmeError> where R::Response: 'r, - 'r: 'a, { - assert_ne!(size_of::(), 0); - assert!(size_of::() <= 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 { diff --git a/src/mem/mod.rs b/src/mem/mod.rs index 4c607c57..307c9cb5 100644 --- a/src/mem/mod.rs +++ b/src/mem/mod.rs @@ -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; diff --git a/src/mem/phys/manager.rs b/src/mem/phys/manager.rs index 3cde108f..9e8106ec 100644 --- a/src/mem/phys/manager.rs +++ b/src/mem/phys/manager.rs @@ -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; diff --git a/src/mem/phys/mod.rs b/src/mem/phys/mod.rs index b1837c28..283e829a 100644 --- a/src/mem/phys/mod.rs +++ b/src/mem/phys/mod.rs @@ -208,3 +208,13 @@ fn kernel_physical_memory_region() -> PhysicalMemoryRegion { PhysicalMemoryRegion { base, size } } + +#[no_mangle] +fn __allocate_contiguous_pages(count: usize) -> Result { + alloc_pages_contiguous(count) +} + +#[no_mangle] +unsafe fn __free_page(page: PhysicalAddress) { + free_page(page) +} diff --git a/src/proc/elf.rs b/src/proc/elf.rs index 633b8cef..50193b1b 100644 --- a/src/proc/elf.rs +++ b/src/proc/elf.rs @@ -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}, }; diff --git a/src/proc/exec.rs b/src/proc/exec.rs index 24d88b44..dacc0ca3 100644 --- a/src/proc/exec.rs +++ b/src/proc/exec.rs @@ -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>( 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::>(); if shebang_args.is_empty() || shebang_args.len() >= 8 { diff --git a/tools/gentables/src/x86_64.rs b/tools/gentables/src/x86_64.rs index 725636e3..87aa5c45 100644 --- a/tools/gentables/src/x86_64.rs +++ b/tools/gentables/src/x86_64.rs @@ -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 { } 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;