***: fix incorrect tlbi + add Read/OpenDirectory
This commit is contained in:
parent
64233db3df
commit
867edf7748
@ -2,8 +2,11 @@ use core::marker::PhantomData;
|
|||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
use vfs::{Vnode, VnodeImpl, VnodeKind, VnodeRef};
|
use vfs::{Vnode, VnodeImpl, VnodeKind, VnodeRef, DIR_POSITION_FROM_CACHE};
|
||||||
use yggdrasil_abi::error::Error;
|
use yggdrasil_abi::{
|
||||||
|
error::Error,
|
||||||
|
io::{FileMode, OpenOptions},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{block::BlockAllocator, bvec::BVec, file::FileNode};
|
use crate::{block::BlockAllocator, bvec::BVec, file::FileNode};
|
||||||
|
|
||||||
@ -23,6 +26,15 @@ impl<A: BlockAllocator> VnodeImpl for DirectoryNode<A> {
|
|||||||
}
|
}
|
||||||
Ok(child)
|
Ok(child)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn open(
|
||||||
|
&mut self,
|
||||||
|
_node: &VnodeRef,
|
||||||
|
_opts: OpenOptions,
|
||||||
|
_mode: FileMode,
|
||||||
|
) -> Result<u64, Error> {
|
||||||
|
Ok(DIR_POSITION_FROM_CACHE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: BlockAllocator> DirectoryNode<A> {
|
impl<A: BlockAllocator> DirectoryNode<A> {
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
use core::cell::RefCell;
|
use core::{cell::RefCell, mem::MaybeUninit};
|
||||||
|
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use yggdrasil_abi::error::Error;
|
use yggdrasil_abi::{
|
||||||
|
error::Error,
|
||||||
|
io::{DirectoryEntry, FileType},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
node::{VnodeKind, VnodeRef},
|
node::{VnodeKind, VnodeRef},
|
||||||
Read, Seek, SeekFrom, Write,
|
Read, ReadDirectory, Seek, SeekFrom, Write, DIR_POSITION_FROM_CACHE,
|
||||||
};
|
};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
@ -18,13 +21,28 @@ bitflags! {
|
|||||||
|
|
||||||
pub type FileRef = Rc<RefCell<File>>;
|
pub type FileRef = Rc<RefCell<File>>;
|
||||||
|
|
||||||
|
enum DirectoryPosition {
|
||||||
|
DiskPosition(u64),
|
||||||
|
// TODO not the best implementation, but at least somewhat safe?
|
||||||
|
CachePosition(usize),
|
||||||
|
Dot,
|
||||||
|
DotDot,
|
||||||
|
End,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct NormalFile {
|
pub struct NormalFile {
|
||||||
vnode: VnodeRef,
|
vnode: VnodeRef,
|
||||||
pos: u64,
|
pos: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Directory {
|
||||||
|
vnode: VnodeRef,
|
||||||
|
pos: DirectoryPosition,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum FileInner {
|
pub enum FileInner {
|
||||||
Normal(NormalFile),
|
Normal(NormalFile),
|
||||||
|
Directory(Directory),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
@ -39,6 +57,20 @@ impl File {
|
|||||||
flags,
|
flags,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn directory(vnode: VnodeRef, pos: u64) -> FileRef {
|
||||||
|
let pos = if pos == DIR_POSITION_FROM_CACHE {
|
||||||
|
// Read from cache
|
||||||
|
DirectoryPosition::Dot
|
||||||
|
} else {
|
||||||
|
// Reading from a "physical" directory
|
||||||
|
todo!()
|
||||||
|
};
|
||||||
|
Rc::new(RefCell::new(Self {
|
||||||
|
inner: FileInner::Directory(Directory { vnode, pos }),
|
||||||
|
flags: FileFlags::READ,
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Write for File {
|
impl Write for File {
|
||||||
@ -55,6 +87,7 @@ impl Write for File {
|
|||||||
}
|
}
|
||||||
Ok(count)
|
Ok(count)
|
||||||
}
|
}
|
||||||
|
FileInner::Directory(_) => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,6 +106,7 @@ impl Read for File {
|
|||||||
}
|
}
|
||||||
Ok(count)
|
Ok(count)
|
||||||
}
|
}
|
||||||
|
FileInner::Directory(_) => Err(Error::IsADirectory),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,16 +132,78 @@ impl Seek for File {
|
|||||||
|
|
||||||
Ok(pos)
|
Ok(pos)
|
||||||
}
|
}
|
||||||
|
FileInner::Directory(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ReadDirectory for File {
|
||||||
|
fn read_dir_entries(
|
||||||
|
&mut self,
|
||||||
|
entries: &mut [MaybeUninit<DirectoryEntry>],
|
||||||
|
) -> Result<usize, Error> {
|
||||||
|
let FileInner::Directory(inner) = &mut self.inner else {
|
||||||
|
return Err(Error::NotADirectory);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut nread = 0;
|
||||||
|
let mut rem = entries.len();
|
||||||
|
|
||||||
|
while rem != 0 {
|
||||||
|
let mut entry = DirectoryEntry {
|
||||||
|
name: [0; 256],
|
||||||
|
ty: FileType::File,
|
||||||
|
};
|
||||||
|
|
||||||
|
let next_position = match inner.pos {
|
||||||
|
DirectoryPosition::End => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DirectoryPosition::Dot => {
|
||||||
|
entry.name[0] = b'.';
|
||||||
|
entry.ty = FileType::Directory;
|
||||||
|
DirectoryPosition::DotDot
|
||||||
|
}
|
||||||
|
DirectoryPosition::DotDot => {
|
||||||
|
entry.name[..2].copy_from_slice(b"..");
|
||||||
|
entry.ty = FileType::Directory;
|
||||||
|
DirectoryPosition::CachePosition(0)
|
||||||
|
}
|
||||||
|
DirectoryPosition::CachePosition(index) => {
|
||||||
|
let child = inner.vnode.child_at(index);
|
||||||
|
|
||||||
|
if let Some(child) = child {
|
||||||
|
let child_name = child.name();
|
||||||
|
entry.name[..child_name.len()].copy_from_slice(child_name.as_bytes());
|
||||||
|
entry.ty = FileType::from(child.kind());
|
||||||
|
DirectoryPosition::CachePosition(index + 1)
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DirectoryPosition::DiskPosition(_) => todo!(),
|
||||||
|
};
|
||||||
|
inner.pos = next_position;
|
||||||
|
|
||||||
|
entries[nread].write(entry);
|
||||||
|
|
||||||
|
nread += 1;
|
||||||
|
rem -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(nread)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Drop for File {
|
impl Drop for File {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
match &mut self.inner {
|
match &mut self.inner {
|
||||||
FileInner::Normal(inner) => {
|
FileInner::Normal(inner) => {
|
||||||
inner.vnode.close().ok();
|
inner.vnode.close().ok();
|
||||||
}
|
}
|
||||||
|
FileInner::Directory(inner) => {
|
||||||
|
inner.vnode.close().ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
use yggdrasil_abi::error::Error;
|
use yggdrasil_abi::error::Error;
|
||||||
|
use yggdrasil_abi::io::DirectoryEntry;
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
@ -24,6 +27,8 @@ pub use fs::Filesystem;
|
|||||||
pub use ioctx::IoContext;
|
pub use ioctx::IoContext;
|
||||||
pub use node::{Vnode, VnodeDump, VnodeImpl, VnodeKind, VnodeRef, VnodeWeak};
|
pub use node::{Vnode, VnodeDump, VnodeImpl, VnodeKind, VnodeRef, VnodeWeak};
|
||||||
|
|
||||||
|
pub const DIR_POSITION_FROM_CACHE: u64 = u64::MAX;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SeekFrom {
|
pub enum SeekFrom {
|
||||||
Start(u64),
|
Start(u64),
|
||||||
@ -47,6 +52,13 @@ pub trait Seek {
|
|||||||
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error>;
|
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ReadDirectory {
|
||||||
|
fn read_dir_entries(
|
||||||
|
&mut self,
|
||||||
|
entries: &mut [MaybeUninit<DirectoryEntry>],
|
||||||
|
) -> Result<usize, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<(), Error> {
|
fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<(), Error> {
|
||||||
while !buf.is_empty() {
|
while !buf.is_empty() {
|
||||||
match this.read(buf) {
|
match this.read(buf) {
|
||||||
|
@ -11,12 +11,13 @@ use alloc::{
|
|||||||
};
|
};
|
||||||
use yggdrasil_abi::{
|
use yggdrasil_abi::{
|
||||||
error::Error,
|
error::Error,
|
||||||
io::{FileMode, OpenOptions},
|
io::{FileMode, FileType, OpenOptions},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
file::{File, FileFlags, FileRef},
|
file::{File, FileFlags, FileRef},
|
||||||
fs::Filesystem,
|
fs::Filesystem,
|
||||||
|
DIR_POSITION_FROM_CACHE,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type VnodeRef = Rc<Vnode>;
|
pub type VnodeRef = Rc<Vnode>;
|
||||||
@ -163,6 +164,11 @@ impl Vnode {
|
|||||||
parent_borrow.children.push(child);
|
parent_borrow.children.push(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn child_at(self: &VnodeRef, index: usize) -> Option<VnodeRef> {
|
||||||
|
let tree = self.tree.borrow();
|
||||||
|
tree.children.get(index).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dump(&self, f: &mut fmt::Formatter<'_>, depth: usize, indent: bool) -> fmt::Result {
|
pub fn dump(&self, f: &mut fmt::Formatter<'_>, depth: usize, indent: bool) -> fmt::Result {
|
||||||
if indent {
|
if indent {
|
||||||
for _ in 0..depth {
|
for _ in 0..depth {
|
||||||
@ -244,11 +250,25 @@ impl Vnode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn open_directory(self: &VnodeRef) -> Result<FileRef, Error> {
|
||||||
|
if !self.is_directory() {
|
||||||
|
return Err(Error::IsADirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref mut data) = *self.data() {
|
||||||
|
let pos = data.open(self, OpenOptions::READ, FileMode::empty())?;
|
||||||
|
Ok(File::directory(self.clone(), pos))
|
||||||
|
} else {
|
||||||
|
// TODO: some options here?
|
||||||
|
Ok(File::directory(self.clone(), DIR_POSITION_FROM_CACHE))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn close(self: &VnodeRef) -> Result<(), Error> {
|
pub fn close(self: &VnodeRef) -> Result<(), Error> {
|
||||||
if let Some(ref mut data) = *self.data() {
|
if let Some(ref mut data) = *self.data() {
|
||||||
data.close(self)
|
data.close(self)
|
||||||
} else {
|
} else {
|
||||||
todo!()
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,3 +397,14 @@ impl fmt::Debug for VnodeDump {
|
|||||||
self.node.dump(f, 0, true)
|
self.node.dump(f, 0, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<VnodeKind> for FileType {
|
||||||
|
fn from(value: VnodeKind) -> Self {
|
||||||
|
match value {
|
||||||
|
VnodeKind::Regular => Self::File,
|
||||||
|
VnodeKind::Directory => Self::Directory,
|
||||||
|
VnodeKind::Block => Self::Block,
|
||||||
|
VnodeKind::Char => Self::Char,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -232,13 +232,13 @@ pub fn kernel_main(dtb_phys: usize) -> ! {
|
|||||||
devfs::init();
|
devfs::init();
|
||||||
PLATFORM.init(true).unwrap();
|
PLATFORM.init(true).unwrap();
|
||||||
|
|
||||||
let dt = ARCHITECTURE.dt.get();
|
// let dt = ARCHITECTURE.dt.get();
|
||||||
if let Err(e) = smp::start_ap_cores(dt) {
|
// if let Err(e) = smp::start_ap_cores(dt) {
|
||||||
errorln!(
|
// errorln!(
|
||||||
"Could not initialize AP CPUs: {:?}. Will continue with one CPU.",
|
// "Could not initialize AP CPUs: {:?}. Will continue with one CPU.",
|
||||||
e
|
// e
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
Cpu::init_ipi_queues();
|
Cpu::init_ipi_queues();
|
||||||
|
|
||||||
|
@ -5,8 +5,10 @@ use core::{
|
|||||||
sync::atomic::{AtomicU8, Ordering},
|
sync::atomic::{AtomicU8, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use aarch64_cpu::registers::DAIF;
|
||||||
use abi::error::Error;
|
use abi::error::Error;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
use tock_registers::interfaces::Readable;
|
||||||
|
|
||||||
use crate::mem::{
|
use crate::mem::{
|
||||||
phys::{self, PageUsage},
|
phys::{self, PageUsage},
|
||||||
@ -77,6 +79,8 @@ bitflags! {
|
|||||||
const AP_BOTH_READWRITE = 1 << 6;
|
const AP_BOTH_READWRITE = 1 << 6;
|
||||||
/// For page/block mappings, only allows read access for EL0/EL1
|
/// For page/block mappings, only allows read access for EL0/EL1
|
||||||
const AP_BOTH_READONLY = 3 << 6;
|
const AP_BOTH_READONLY = 3 << 6;
|
||||||
|
|
||||||
|
const NON_GLOBAL = 1 << 11;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,8 +305,6 @@ impl FixedTables {
|
|||||||
}
|
}
|
||||||
self.device_l3i += count;
|
self.device_l3i += count;
|
||||||
|
|
||||||
tlb_flush_vaae1(virt);
|
|
||||||
|
|
||||||
Ok(virt)
|
Ok(virt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,6 +317,9 @@ impl VirtualMemoryManager for AddressSpace {
|
|||||||
len: usize,
|
len: usize,
|
||||||
attrs: PageAttributes,
|
attrs: PageAttributes,
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
|
assert_eq!(DAIF.read(DAIF::I), 1);
|
||||||
|
|
||||||
|
assert_eq!(len, 1);
|
||||||
if hint.is_some() {
|
if hint.is_some() {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
@ -341,12 +346,17 @@ impl VirtualMemoryManager for AddressSpace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn deallocate(&self, addr: usize, len: usize) -> Result<(), Error> {
|
fn deallocate(&self, addr: usize, len: usize) -> Result<(), Error> {
|
||||||
|
assert_eq!(DAIF.read(DAIF::I), 1);
|
||||||
|
|
||||||
for page in (addr..addr + len).step_by(0x1000) {
|
for page in (addr..addr + len).step_by(0x1000) {
|
||||||
let Some(_phys) = self.translate(page) else {
|
let Some(phys) = self.translate(page) else {
|
||||||
todo!();
|
todo!();
|
||||||
};
|
};
|
||||||
|
|
||||||
self.write_entry(page, PageEntry::INVALID, true)?;
|
self.write_entry(page, PageEntry::INVALID, true)?;
|
||||||
|
unsafe {
|
||||||
|
phys::free_page(phys);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -402,6 +412,8 @@ impl AddressSpace {
|
|||||||
}
|
}
|
||||||
l3[l3i] = entry;
|
l3[l3i] = entry;
|
||||||
|
|
||||||
|
tlb_flush_vaae1(virt);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,11 +428,11 @@ impl AddressSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flushes the virtual address from TLB
|
/// Flush a virtual address from EL1/EL0 TLB for all ASIDs
|
||||||
pub fn tlb_flush_vaae1(page: usize) {
|
pub fn tlb_flush_vaae1(mut page: usize) {
|
||||||
assert_eq!(page & 0xFFF, 0);
|
page >>= 12;
|
||||||
unsafe {
|
unsafe {
|
||||||
core::arch::asm!("tlbi vaae1, {addr}", addr = in(reg) page);
|
core::arch::asm!("tlbi vaae1, {page}", page = in(reg) page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +78,14 @@ impl PhysicalMemoryManager {
|
|||||||
Err(Error::OutOfMemory)
|
Err(Error::OutOfMemory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn free_page(&mut self, addr: usize) {
|
||||||
|
assert!(addr > self.offset);
|
||||||
|
let index = (addr - self.offset) / 0x1000;
|
||||||
|
let page = &mut self.pages[index];
|
||||||
|
assert_eq!(page.usage, PageUsage::Used);
|
||||||
|
page.usage = PageUsage::Available;
|
||||||
|
}
|
||||||
|
|
||||||
/// Marks a previously reserved page as available.
|
/// Marks a previously reserved page as available.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
|
@ -10,6 +10,7 @@ use crate::{
|
|||||||
phys::reserved::{is_reserved, reserve_region},
|
phys::reserved::{is_reserved, reserve_region},
|
||||||
ConvertAddress, KERNEL_PHYS_BASE,
|
ConvertAddress, KERNEL_PHYS_BASE,
|
||||||
},
|
},
|
||||||
|
sync::IrqSafeSpinlock,
|
||||||
util::OneTimeInit,
|
util::OneTimeInit,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -64,7 +65,8 @@ impl PhysicalMemoryRegion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Global physical memory manager
|
/// Global physical memory manager
|
||||||
pub static PHYSICAL_MEMORY: OneTimeInit<Spinlock<PhysicalMemoryManager>> = OneTimeInit::new();
|
pub static PHYSICAL_MEMORY: OneTimeInit<IrqSafeSpinlock<PhysicalMemoryManager>> =
|
||||||
|
OneTimeInit::new();
|
||||||
|
|
||||||
/// Allocates a single physical page from the global manager
|
/// Allocates a single physical page from the global manager
|
||||||
pub fn alloc_page(usage: PageUsage) -> Result<usize, Error> {
|
pub fn alloc_page(usage: PageUsage) -> Result<usize, Error> {
|
||||||
@ -79,6 +81,10 @@ pub fn alloc_pages_contiguous(count: usize, usage: PageUsage) -> Result<usize, E
|
|||||||
.alloc_contiguous_pages(count, usage)
|
.alloc_contiguous_pages(count, usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn free_page(addr: usize) {
|
||||||
|
PHYSICAL_MEMORY.get().lock().free_page(addr)
|
||||||
|
}
|
||||||
|
|
||||||
fn physical_memory_range<I: Iterator<Item = PhysicalMemoryRegion>>(
|
fn physical_memory_range<I: Iterator<Item = PhysicalMemoryRegion>>(
|
||||||
it: I,
|
it: I,
|
||||||
) -> Option<(usize, usize)> {
|
) -> Option<(usize, usize)> {
|
||||||
@ -182,7 +188,7 @@ pub unsafe fn init_from_iter<I: Iterator<Item = PhysicalMemoryRegion> + Clone>(
|
|||||||
|
|
||||||
infoln!("{} available pages", page_count);
|
infoln!("{} available pages", page_count);
|
||||||
|
|
||||||
PHYSICAL_MEMORY.init(Spinlock::new(manager));
|
PHYSICAL_MEMORY.init(IrqSafeSpinlock::new(manager));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ where
|
|||||||
(_, 0) => PageAttributes::AP_BOTH_READWRITE,
|
(_, 0) => PageAttributes::AP_BOTH_READWRITE,
|
||||||
(0, _) => PageAttributes::AP_BOTH_READONLY,
|
(0, _) => PageAttributes::AP_BOTH_READONLY,
|
||||||
(_, _) => PageAttributes::AP_BOTH_READWRITE,
|
(_, _) => PageAttributes::AP_BOTH_READWRITE,
|
||||||
};
|
} | PageAttributes::NON_GLOBAL;
|
||||||
|
|
||||||
let dst_page_off = addr & 0xFFF;
|
let dst_page_off = addr & 0xFFF;
|
||||||
let dst_page_aligned = addr & !0xFFF;
|
let dst_page_aligned = addr & !0xFFF;
|
||||||
|
@ -32,7 +32,11 @@ fn setup_args(space: &AddressSpace, virt: usize, args: &[&str]) -> Result<(), Er
|
|||||||
|
|
||||||
let phys_page = phys::alloc_page(PageUsage::Used)?;
|
let phys_page = phys::alloc_page(PageUsage::Used)?;
|
||||||
// TODO check if this doesn't overwrite anything
|
// TODO check if this doesn't overwrite anything
|
||||||
space.map_page(virt, phys_page, PageAttributes::AP_BOTH_READWRITE)?;
|
space.map_page(
|
||||||
|
virt,
|
||||||
|
phys_page,
|
||||||
|
PageAttributes::AP_BOTH_READWRITE | PageAttributes::NON_GLOBAL,
|
||||||
|
)?;
|
||||||
|
|
||||||
let write = unsafe { phys_page.virtualize() };
|
let write = unsafe { phys_page.virtualize() };
|
||||||
|
|
||||||
@ -70,7 +74,7 @@ fn setup_args(space: &AddressSpace, virt: usize, args: &[&str]) -> Result<(), Er
|
|||||||
fn setup_binary(space: AddressSpace, entry: usize, args: &[&str]) -> Result<Rc<Process>, Error> {
|
fn setup_binary(space: AddressSpace, entry: usize, args: &[&str]) -> Result<Rc<Process>, Error> {
|
||||||
const USER_STACK_PAGES: usize = 8;
|
const USER_STACK_PAGES: usize = 8;
|
||||||
|
|
||||||
let virt_stack_base = 0x10000000;
|
let virt_stack_base = 0x3000000;
|
||||||
// 0x1000 of guard page
|
// 0x1000 of guard page
|
||||||
let virt_args_base = virt_stack_base + (USER_STACK_PAGES + 1) * 0x1000;
|
let virt_args_base = virt_stack_base + (USER_STACK_PAGES + 1) * 0x1000;
|
||||||
|
|
||||||
@ -79,7 +83,7 @@ fn setup_binary(space: AddressSpace, entry: usize, args: &[&str]) -> Result<Rc<P
|
|||||||
space.map_page(
|
space.map_page(
|
||||||
virt_stack_base + i * 0x1000,
|
virt_stack_base + i * 0x1000,
|
||||||
phys,
|
phys,
|
||||||
PageAttributes::AP_BOTH_READWRITE,
|
PageAttributes::AP_BOTH_READWRITE | PageAttributes::NON_GLOBAL,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use core::alloc::Layout;
|
use core::alloc::Layout;
|
||||||
|
|
||||||
|
use abi::io::RawFd;
|
||||||
use yggdrasil_abi::error::Error;
|
use yggdrasil_abi::error::Error;
|
||||||
|
|
||||||
pub(super) fn arg_buffer_ref<'a>(base: usize, len: usize) -> Result<&'a [u8], Error> {
|
pub(super) fn arg_buffer_ref<'a>(base: usize, len: usize) -> Result<&'a [u8], Error> {
|
||||||
@ -18,6 +19,9 @@ pub(super) fn arg_buffer_mut<'a>(base: usize, len: usize) -> Result<&'a mut [u8]
|
|||||||
|
|
||||||
pub(super) fn arg_user_str<'a>(base: usize, len: usize) -> Result<&'a str, Error> {
|
pub(super) fn arg_user_str<'a>(base: usize, len: usize) -> Result<&'a str, Error> {
|
||||||
let slice = arg_buffer_ref(base, len)?;
|
let slice = arg_buffer_ref(base, len)?;
|
||||||
|
if slice.contains(&0) {
|
||||||
|
todo!("Incorrect ptr: {:#x}", base);
|
||||||
|
}
|
||||||
Ok(core::str::from_utf8(slice).unwrap())
|
Ok(core::str::from_utf8(slice).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,3 +34,29 @@ pub(super) fn arg_user_ref<'a, T: Sized>(addr: usize) -> Result<&'a T, Error> {
|
|||||||
let value = unsafe { core::mem::transmute::<_, &'a T>(addr) };
|
let value = unsafe { core::mem::transmute::<_, &'a T>(addr) };
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn arg_user_slice_mut<'a, T: Sized>(
|
||||||
|
base: usize,
|
||||||
|
count: usize,
|
||||||
|
) -> Result<&'a mut [T], Error> {
|
||||||
|
let layout = Layout::array::<T>(count).unwrap();
|
||||||
|
|
||||||
|
if base % layout.align() != 0 {
|
||||||
|
todo!("Misaligned buffer");
|
||||||
|
}
|
||||||
|
|
||||||
|
if base + layout.size() > crate::mem::KERNEL_VIRT_OFFSET {
|
||||||
|
panic!("Invalid argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
let slice = unsafe { core::slice::from_raw_parts_mut(base as *mut _, count) };
|
||||||
|
Ok(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn arg_option_fd(raw: u32) -> Option<RawFd> {
|
||||||
|
if raw == u32::MAX {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(RawFd(raw))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
//! System function call handlers
|
//! System function call handlers
|
||||||
use core::time::Duration;
|
use core::{mem::MaybeUninit, sync::atomic::AtomicUsize, time::Duration};
|
||||||
|
|
||||||
use abi::{
|
use abi::{
|
||||||
error::Error,
|
error::Error,
|
||||||
io::{FileMode, OpenOptions, RawFd},
|
io::{DirectoryEntry, FileMode, OpenOptions, RawFd},
|
||||||
syscall::SyscallFunction,
|
syscall::SyscallFunction,
|
||||||
};
|
};
|
||||||
use vfs::{Read, Write};
|
use vfs::{Read, ReadDirectory, Write};
|
||||||
use yggdrasil_abi::{
|
use yggdrasil_abi::{
|
||||||
error::SyscallResult,
|
error::SyscallResult,
|
||||||
io::{MountOptions, UnmountOptions},
|
io::{MountOptions, UnmountOptions},
|
||||||
@ -58,10 +58,11 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
|
|||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
let addr = space.allocate(None, len / 0x1000, PageAttributes::AP_BOTH_READWRITE);
|
space.allocate(
|
||||||
debugln!("mmap({:#x}) = {:x?}", len, addr);
|
None,
|
||||||
|
len / 0x1000,
|
||||||
addr
|
PageAttributes::AP_BOTH_READWRITE | PageAttributes::NON_GLOBAL,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
SyscallFunction::UnmapMemory => {
|
SyscallFunction::UnmapMemory => {
|
||||||
let addr = args[0] as usize;
|
let addr = args[0] as usize;
|
||||||
@ -74,7 +75,6 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
|
|||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
debugln!("munmap({:#x}, {:#x})", addr, len);
|
|
||||||
space.deallocate(addr, len)?;
|
space.deallocate(addr, len)?;
|
||||||
|
|
||||||
Ok(0)
|
Ok(0)
|
||||||
@ -154,6 +154,37 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
|
|||||||
|
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
SyscallFunction::OpenDirectory => {
|
||||||
|
let at = arg_option_fd(args[0] as u32);
|
||||||
|
let path = arg_user_str(args[1] as usize, args[2] as usize)?;
|
||||||
|
|
||||||
|
let proc = Process::current();
|
||||||
|
let mut io = proc.io.lock();
|
||||||
|
|
||||||
|
// TODO handle at
|
||||||
|
assert!(at.is_none());
|
||||||
|
|
||||||
|
let node = io.ioctx().find(None, path, true, true)?;
|
||||||
|
let file = node.open_directory()?;
|
||||||
|
let fd = io.place_file(file)?;
|
||||||
|
|
||||||
|
Ok(fd.0 as usize)
|
||||||
|
}
|
||||||
|
SyscallFunction::ReadDirectory => {
|
||||||
|
let fd = RawFd(args[0] as u32);
|
||||||
|
let buffer = arg_user_slice_mut::<MaybeUninit<DirectoryEntry>>(
|
||||||
|
args[1] as usize,
|
||||||
|
args[2] as usize,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let proc = Process::current();
|
||||||
|
let mut io = proc.io.lock();
|
||||||
|
|
||||||
|
let file = io.file(fd)?;
|
||||||
|
let mut file_borrow = file.borrow_mut();
|
||||||
|
|
||||||
|
file_borrow.read_dir_entries(buffer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user