Skip to content

Commit

Permalink
Initialize shm_open implementation (#651)
Browse files Browse the repository at this point in the history
Co-authored-by: Marcin Mikołajczyk <[email protected]>
Co-authored-by: Putta Khunchalee <[email protected]>
  • Loading branch information
3 people committed Feb 16, 2024
1 parent 2c3b381 commit 7e2563a
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 3 deletions.
12 changes: 11 additions & 1 deletion src/kernel/src/fs/file.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use super::{IoCmd, Offset, Stat, Uio, UioMut, Vnode};
use crate::dmem::BlockPool;
use crate::errno::Errno;
use crate::errno::{ENOTTY, ENXIO};
use crate::errno::{ENOTTY, ENXIO, EOPNOTSUPP};
use crate::kqueue::KernelQueue;
use crate::net::Socket;
use crate::process::VThread;
use crate::shm::Shm;
use bitflags::bitflags;
use macros::Errno;
use std::fmt::Debug;
Expand Down Expand Up @@ -85,6 +86,7 @@ impl VFile {
VFileType::Vnode(vn) => vn.read(self, buf, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.read(self, buf, td),
VFileType::KernelQueue(kq) => kq.read(self, buf, td),
VFileType::SharedMemory(shm) => shm.read(self, buf, td),
VFileType::Blockpool(bp) => bp.read(self, buf, td),
}
}
Expand All @@ -94,6 +96,7 @@ impl VFile {
VFileType::Vnode(vn) => vn.write(self, buf, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.write(self, buf, td),
VFileType::KernelQueue(kq) => kq.write(self, buf, td),
VFileType::SharedMemory(shm) => shm.write(self, buf, td),
VFileType::Blockpool(bp) => bp.write(self, buf, td),
}
}
Expand All @@ -104,6 +107,7 @@ impl VFile {
VFileType::Vnode(vn) => vn.ioctl(self, cmd, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.ioctl(self, cmd, td),
VFileType::KernelQueue(kq) => kq.ioctl(self, cmd, td),
VFileType::SharedMemory(shm) => shm.ioctl(self, cmd, td),
VFileType::Blockpool(bp) => bp.ioctl(self, cmd, td),
}
}
Expand All @@ -113,6 +117,7 @@ impl VFile {
VFileType::Vnode(vn) => vn.stat(self, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.stat(self, td),
VFileType::KernelQueue(kq) => kq.stat(self, td),
VFileType::SharedMemory(shm) => shm.stat(self, td),
VFileType::Blockpool(bp) => bp.stat(self, td),
}
}
Expand Down Expand Up @@ -150,6 +155,7 @@ pub enum VFileType {
Vnode(Arc<Vnode>), // DTYPE_VNODE = 1
Socket(Arc<Socket>), // DTYPE_SOCKET = 2,
KernelQueue(Arc<KernelQueue>), // DTYPE_KQUEUE = 5,
SharedMemory(Arc<Shm>), // DTYPE_SHM = 8,
IpcSocket(Arc<Socket>), // DTYPE_IPCSOCKET = 15,
Blockpool(Arc<BlockPool>), // DTYPE_BLOCKPOOL = 17,
}
Expand Down Expand Up @@ -212,4 +218,8 @@ pub enum DefaultError {
#[error("iocll is not supported")]
#[errno(ENOTTY)]
IoctlNotSupported,

#[error("operation is not supported")]
#[errno(EOPNOTSUPP)]
OperationNotSupported,
}
6 changes: 5 additions & 1 deletion src/kernel/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,13 +845,17 @@ impl Fs {

bitflags! {
/// Flags for [`Fs::sys_open()`].
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct OpenFlags: u32 {
const O_RDONLY = 0x00000000;
const O_WRONLY = 0x00000001;
const O_RDWR = 0x00000002;
const O_ACCMODE = Self::O_WRONLY.bits() | Self::O_RDWR.bits();
const O_SHLOCK = 0x00000010;
const O_EXLOCK = 0x00000020;
const O_CREAT = 0x00000200;
const O_TRUNC = 0x00000400;
const O_EXCL = 0x00000800;
const O_EXEC = 0x00040000;
const O_CLOEXEC = 0x00100000;
const UNK1 = 0x00400000;
Expand All @@ -860,7 +864,7 @@ bitflags! {

impl OpenFlags {
/// An implementation of `FFLAGS` macro.
fn into_fflags(self) -> VFileFlags {
pub fn into_fflags(self) -> VFileFlags {
VFileFlags::from_bits_truncate(self.bits() + 1)
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/kernel/src/fs/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@ impl Borrow<VPath> for VPathBuf {
}
}

impl PartialEq<VPath> for VPathBuf {
fn eq(&self, other: &VPath) -> bool {
self.0 == other.0
}
}

impl Display for VPathBuf {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
Expand Down
1 change: 1 addition & 0 deletions src/kernel/src/fs/perm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ bitflags! {
pub struct Access: u32 {
const EXEC = 0o00000000100; // VEXEC
const WRITE = 0o00000000200; // VWRITE
const READ = 0o00000000400; // VREAD
const ADMIN = 0o00000010000; // VADMIN
const EXPLICIT_DENY = 0o00000100000; // VEXPLICIT_DENY
const DELETE_CHILD = 0o00001000000; // VDELETE_CHILD
Expand Down
2 changes: 1 addition & 1 deletion src/kernel/src/fs/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub struct Stat {
atime: TimeSpec,
mtime: TimeSpec,
ctime: TimeSpec,
size: i64,
pub size: i64,
block_count: i64,
pub block_size: u32,
flags: u32,
Expand Down
3 changes: 3 additions & 0 deletions src/kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::osem::OsemManager;
use crate::process::{VProc, VProcInitError, VThread};
use crate::regmgr::RegMgr;
use crate::rtld::{LoadFlags, ModuleFlags, RuntimeLinker};
use crate::shm::SharedMemoryManager;
use crate::syscalls::Syscalls;
use crate::sysctl::Sysctl;
use crate::time::TimeManager;
Expand Down Expand Up @@ -51,6 +52,7 @@ mod osem;
mod process;
mod regmgr;
mod rtld;
mod shm;
mod signal;
mod syscalls;
mod sysctl;
Expand Down Expand Up @@ -269,6 +271,7 @@ fn run<E: crate::ee::ExecutionEngine>(
let budget = BudgetManager::new(&mut syscalls);

DmemManager::new(fs, &mut syscalls);
SharedMemoryManager::new(mm, &mut syscalls);
Sysctl::new(mm, &machdep, &mut syscalls);
TimeManager::new(&mut syscalls);
KernelQueueManager::new(&mut syscalls);
Expand Down
15 changes: 15 additions & 0 deletions src/kernel/src/process/filedesc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct FileDesc {
cwd: Gutex<Arc<Vnode>>, // fd_cdir
root: Gutex<Arc<Vnode>>, // fd_rdir
kqueue_list: Gutex<VecDeque<Arc<KernelQueue>>>, // fd_kqlist
cmask: u32, // fd_cmask
}

impl FileDesc {
Expand All @@ -29,6 +30,7 @@ impl FileDesc {
cwd: gg.spawn(root.clone()),
root: gg.spawn(root),
kqueue_list: gg.spawn(VecDeque::new()),
cmask: 0o22, // TODO: verify this
};

Arc::new(filedesc)
Expand All @@ -46,6 +48,10 @@ impl FileDesc {
self.kqueue_list.write().push_front(kq);
}

pub fn cmask(&self) -> u32 {
self.cmask
}

#[allow(unused_variables)] // TODO: remove when implementing; add budget argument
pub fn alloc_with_budget<E: Errno>(
&self,
Expand All @@ -56,6 +62,15 @@ impl FileDesc {
todo!()
}

#[allow(unused_variables)] // TODO: remove when implementing;
pub fn alloc_without_budget<E: Errno>(
&self,
constructor: impl FnOnce(i32) -> Result<VFileType, E>,
flags: VFileFlags,
) -> Result<i32, FileAllocError<E>> {
todo!()
}

/// See `finstall` on the PS4 for a reference.
pub fn alloc(&self, file: Arc<VFile>) -> i32 {
// TODO: Implement fdalloc.
Expand Down
11 changes: 11 additions & 0 deletions src/kernel/src/process/thread.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::{CpuMask, CpuSet, VProc, NEXT_ID};
use crate::errno::Errno;
use crate::fs::VFile;
use crate::signal::SignalSet;
use crate::ucred::{Privilege, PrivilegeError, Ucred};
Expand All @@ -8,6 +9,7 @@ use llt::{OsThread, SpawnError};
use std::num::NonZeroI32;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use thiserror::Error;
use tls::{Local, Tls};

/// An implementation of `thread` structure for the main application.
Expand Down Expand Up @@ -182,3 +184,12 @@ impl Drop for Running {
}

static VTHREAD: Tls<Arc<VThread>> = Tls::new();

#[derive(Debug, Error)]
pub enum FileAllocError {}

impl Errno for FileAllocError {
fn errno(&self) -> NonZeroI32 {
match *self {}
}
}
149 changes: 149 additions & 0 deletions src/kernel/src/shm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
use crate::{
errno::{Errno, EINVAL},
fs::{
check_access, Access, DefaultError, FileBackend, IoCmd, Mode, OpenFlags, Stat, Uio, UioMut,
VFile, VFileFlags, VPathBuf,
},
memory::MemoryManager,
process::VThread,
syscalls::{SysErr, SysIn, SysOut, Syscalls},
ucred::{Gid, Ucred, Uid},
};
use std::{convert::Infallible, sync::Arc};

pub struct SharedMemoryManager {
mm: Arc<MemoryManager>,
}

impl SharedMemoryManager {
pub fn new(mm: &Arc<MemoryManager>, sys: &mut Syscalls) -> Arc<Self> {
let shm = Arc::new(Self { mm: mm.clone() });

sys.register(482, &shm, Self::sys_shm_open);
sys.register(483, &shm, Self::sys_shm_unlink);

shm
}

fn sys_shm_open(self: &Arc<Self>, i: &SysIn) -> Result<SysOut, SysErr> {
let path = unsafe { i.args[0].to_shm_path() }?.expect("invalid shm path");
let flags: OpenFlags = i.args[1].try_into().unwrap();
let mode: u32 = i.args[2].try_into().unwrap();

if (flags & OpenFlags::O_ACCMODE != OpenFlags::O_RDONLY)
|| (flags & OpenFlags::O_ACCMODE != OpenFlags::O_RDWR)
{
return Err(SysErr::Raw(EINVAL));
}

if !flags
.difference(
OpenFlags::O_ACCMODE | OpenFlags::O_CREAT | OpenFlags::O_EXCL | OpenFlags::O_TRUNC,
)
.is_empty()
{
return Err(SysErr::Raw(EINVAL));
}

let td = VThread::current().unwrap();

let filedesc = td.proc().files();

let mode = mode & filedesc.cmask() & 0o7777;

let fd = filedesc.alloc_without_budget::<Infallible>(
|_| match path {
ShmPath::Anon => {
todo!()
}
ShmPath::Path(path) => {
todo!()
}
},
(flags & OpenFlags::O_ACCMODE).into_fflags(),
)?;

Ok(fd.into())
}

fn sys_shm_unlink(self: &Arc<Self>, i: &SysIn) -> Result<SysOut, SysErr> {
todo!("sys_shm_unlink")
}
}

pub enum ShmPath {
Anon,
Path(VPathBuf),
}

#[derive(Debug)]
pub struct Shm {
uid: Uid,
gid: Gid,
mode: Mode,
}

impl Shm {
/// See `shm_do_truncate` on the PS4 for a reference.
fn truncate(&self, size: usize) {
todo!()
}

/// See `shm_access` on the PS4 for a reference.
fn access(&self, cred: &Ucred, flags: VFileFlags) -> Result<(), Box<dyn Errno>> {
let mut access = Access::empty();

if flags.intersects(VFileFlags::READ) {
access |= Access::READ;
}

if flags.intersects(VFileFlags::WRITE) {
access |= Access::WRITE;
}

check_access(cred, self.uid, self.gid, self.mode, access, false)?;

Ok(())
}
}

impl FileBackend for Shm {
#[allow(unused_variables)]
fn read(
self: &Arc<Self>,
file: &VFile,
buf: &mut UioMut,
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
Err(DefaultError::OperationNotSupported.into())
}

#[allow(unused_variables)]
fn write(
self: &Arc<Self>,
file: &VFile,
buf: &mut Uio,
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
Err(DefaultError::OperationNotSupported.into())
}

#[allow(unused_variables)] // remove when implementing
fn ioctl(
self: &Arc<Self>,
file: &VFile,
cmd: IoCmd,
td: Option<&VThread>,
) -> Result<(), Box<dyn Errno>> {
todo!()
}

#[allow(unused_variables)] // remove when implementing
fn stat(self: &Arc<Self>, file: &VFile, td: Option<&VThread>) -> Result<Stat, Box<dyn Errno>> {
let mut stat = Stat::zeroed();

stat.block_size = 0x4000;

todo!()
}
}
18 changes: 18 additions & 0 deletions src/kernel/src/syscalls/input.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::SysErr;
use crate::errno::{ENAMETOOLONG, ENOENT};
use crate::fs::{VPath, VPathBuf};
use crate::shm::ShmPath;
use std::ffi::{c_char, CStr};
use std::fmt::{Formatter, LowerHex};
use std::num::TryFromIntError;
Expand Down Expand Up @@ -38,6 +39,23 @@ impl SysArg {
Ok(Some(path))
}

pub unsafe fn to_shm_path(self) -> Result<Option<ShmPath>, SysErr> {
match self.0 {
1 => Ok(Some(ShmPath::Anon)),
ptr => {
let slice = unsafe { std::slice::from_raw_parts(ptr as *const u8, 0x400) };

let cstr =
CStr::from_bytes_until_nul(slice).map_err(|_| SysErr::Raw(ENAMETOOLONG))?;

let path = VPath::new(cstr.to_string_lossy().as_ref())
.map(|p| ShmPath::Path(p.to_owned()));

Ok(path)
}
}
}

/// See `copyinstr` on the PS4 for a reference.
pub unsafe fn to_str<'a>(self, max: usize) -> Result<Option<&'a str>, SysErr> {
if self.0 == 0 {
Expand Down
Loading

0 comments on commit 7e2563a

Please sign in to comment.