Skip to content

Commit

Permalink
define some ioctls (#776)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikusp authored Apr 1, 2024
1 parent b0db7bf commit 1cbc0ef
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 24 deletions.
83 changes: 79 additions & 4 deletions src/kernel/src/dev/dmem.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,56 @@
use crate::{
errno::{Errno, EPERM},
errno::{Errno, EINVAL, EPERM},
fs::{CharacterDevice, DeviceDriver, IoCmd},
process::VThread,
syscalls::SysErr,
};
use macros::Errno;
use std::sync::Arc;
use thiserror::Error;

#[derive(Debug)]
struct Dmem {
pub struct Dmem {
total_size: usize, // TODO: Should be 0x13C_000_000
container: DmemContainer,
}

impl Dmem {
pub fn new(total_size: usize, container: DmemContainer) -> Self {
Self {
total_size,
container,
}
}
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum DmemContainer {
pub enum DmemContainer {
Zero,
One,
Two,
}

impl TryInto<DmemContainer> for i32 {
type Error = SysErr;

fn try_into(self) -> Result<DmemContainer, Self::Error> {
match self {
0 => Ok(DmemContainer::Zero),
1 => Ok(DmemContainer::One),
2 => Ok(DmemContainer::Two),
_ => Err(SysErr::Raw(EINVAL)),
}
}
}

impl TryInto<DmemContainer> for usize {
type Error = SysErr;

fn try_into(self) -> Result<DmemContainer, Self::Error> {
(self as i32).try_into()
}
}

impl DeviceDriver for Dmem {
fn ioctl(
&self,
Expand All @@ -33,15 +64,21 @@ impl DeviceDriver for Dmem {
return Err(Box::new(IoctlErr::InsufficientCredentials));
}

let proc_dmem_container = td.proc().dmem_container();

if self.container != DmemContainer::Two
&& self.container as usize != td.proc().dmem_container()
&& self.container != *proc_dmem_container
&& !cred.is_system()
{
return Err(Box::new(IoctlErr::InsufficientCredentials));
}

match cmd {
IoCmd::DMEM10(size) => *size = self.total_size,
IoCmd::DMEMGETPRT(_prt) => todo!(),
IoCmd::DMEMGETAVAIL(_avail) => todo!(),
IoCmd::DMEMALLOC(_alloc) => todo!(),
IoCmd::DMEMQUERY(_query) => todo!(),
_ => todo!(),
}

Expand All @@ -55,3 +92,41 @@ enum IoctlErr {
#[errno(EPERM)]
InsufficientCredentials,
}

#[repr(C)]
#[derive(Debug)]
pub struct PrtAperture {
addr: usize,
len: usize,
id: i64,
}

#[repr(C)]
#[derive(Debug)]
pub struct DmemAvailable {
start_or_phys_out: usize,
end: usize,
align: usize,
size_out: usize,
}

#[repr(C)]
#[derive(Debug)]
pub struct DmemAllocate {
start_or_phys_out: usize,
end: usize,
len: usize,
align: usize,
mem_type: i32,
}

#[repr(C)]
#[derive(Debug)]
pub struct DmemQuery {
dmem_container: i32,
flags: i32,
unk: usize,
phys_addr: usize,
info_out: usize,
info_size: usize,
}
26 changes: 24 additions & 2 deletions src/kernel/src/dmem/blockpool.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::errno::Errno;
use crate::fs::{FileBackend, IoCmd, PollEvents, Stat, VFile};
use crate::fs::{DefaultFileBackendError, FileBackend, IoCmd, PollEvents, Stat, VFile};
use crate::process::VThread;
use std::sync::Arc;

Expand All @@ -14,7 +14,11 @@ impl FileBackend for BlockPool {
cmd: IoCmd,
td: Option<&VThread>,
) -> Result<(), Box<dyn Errno>> {
todo!()
match cmd {
IoCmd::BPOOLEXPAND(args) => todo!(),
IoCmd::BPOOLSTATS(out) => todo!(),
_ => Err(Box::new(DefaultFileBackendError::IoctlNotSupported)),
}
}

#[allow(unused_variables)] // TODO: remove when implementing
Expand All @@ -31,3 +35,21 @@ impl FileBackend for BlockPool {
todo!()
}
}

#[repr(C)]
#[derive(Debug)]
pub struct BlockpoolExpandArgs {
len: usize,
search_start: usize,
search_end: usize,
alignment: usize,
}

#[repr(C)]
#[derive(Debug)]
pub struct BlockpoolStats {
avail_flushed: i32,
avail_cached: i32,
allocated_flushed: i32,
allocated_cached: i32,
}
165 changes: 154 additions & 11 deletions src/kernel/src/dmem/mod.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,128 @@
use thiserror::Error;

use crate::dev::{Dmem, DmemContainer};
use crate::errno::EINVAL;
use crate::fs::Fs;
use crate::process::VThread;
use crate::fs::{make_dev, CharacterDevice, DriverFlags, Fs, MakeDevError, MakeDevFlags, Mode};
use crate::info;
use crate::process::{VProc, VThread};
use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls};
use crate::ucred::{Gid, Privilege, Uid};
use std::ops::Index;
use std::sync::Arc;

pub use self::blockpool::*;

mod blockpool;

#[derive(Debug)]
pub struct DmemDevice {
name: &'static str,
dev: Arc<CharacterDevice>,
}

impl DmemDevice {
pub(super) fn new(name: &'static str, dev: Arc<CharacterDevice>) -> Self {
Self { name, dev }
}
}

/// An implementation of direct memory system on the PS4.
pub struct DmemManager {
fs: Arc<Fs>,
dmem0: DmemDevice,
dmem1: DmemDevice,
dmem2: DmemDevice,
}

impl DmemManager {
pub fn new(fs: &Arc<Fs>, sys: &mut Syscalls) -> Arc<Self> {
let dmem = Arc::new(Self { fs: fs.clone() });
const DMEM_TOTAL_SIZE: usize = 0x13C_000_000;

pub fn new(fs: &Arc<Fs>, sys: &mut Syscalls) -> Result<Arc<Self>, DmemManagerInitError> {
let dmem0 = {
let name = "dmem0";
match make_dev(
Dmem::new(Self::DMEM_TOTAL_SIZE, DmemContainer::Zero),
DriverFlags::D_INIT,
0,
name,
Uid::ROOT,
Gid::ROOT,
Mode::new(0o777).unwrap(),
None,
MakeDevFlags::empty(),
) {
Ok(v) => Ok(DmemDevice::new(name, v)),
Err(e) => Err(DmemManagerInitError::CreateDmemFailed(name, e)),
}
}?;

let dmem1 = {
let name = "dmem1";
match make_dev(
Dmem::new(Self::DMEM_TOTAL_SIZE, DmemContainer::One),
DriverFlags::D_INIT,
0,
name,
Uid::ROOT,
Gid::ROOT,
Mode::new(0o777).unwrap(),
None,
MakeDevFlags::empty(),
) {
Ok(v) => Ok(DmemDevice::new(name, v)),
Err(e) => Err(DmemManagerInitError::CreateDmemFailed(name, e)),
}
}?;

let dmem2 = {
let name = "dmem2";
match make_dev(
Dmem::new(Self::DMEM_TOTAL_SIZE, DmemContainer::Two),
DriverFlags::D_INIT,
0,
name,
Uid::ROOT,
Gid::ROOT,
Mode::new(0o777).unwrap(),
None,
MakeDevFlags::empty(),
) {
Ok(v) => Ok(DmemDevice::new(name, v)),
Err(e) => Err(DmemManagerInitError::CreateDmemFailed(name, e)),
}
}?;

let dmem = Arc::new(Self {
fs: fs.clone(),
dmem0,
dmem1,
dmem2,
});

sys.register(586, &dmem, Self::sys_dmem_container);
sys.register(653, &dmem, Self::sys_blockpool_open);
sys.register(654, &dmem, Self::sys_blockpool_map);
sys.register(655, &dmem, Self::sys_blockpool_unmap);
sys.register(657, &dmem, Self::sys_blockpool_batch);
sys.register(673, &dmem, Self::sys_blockpool_move);

dmem
Ok(dmem)
}

fn sys_dmem_container(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
let set: i32 = i.args[0].try_into().unwrap();
let get: i32 = td.proc().dmem_container().try_into().unwrap();
let dmem_id: i32 = i.args[0].try_into().unwrap();

let mut dmem_container = td.proc().dmem_container_mut();
let old_dmem_container = *dmem_container;

if set != -1 {
todo!("sys_dmem_container with update != -1");
if dmem_id != -1 {
todo!()
}

Ok(get.into())
Ok(old_dmem_container.into())
}

fn sys_blockpool_open(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
fn sys_blockpool_open(self: &Arc<Self>, _td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
let flags: u32 = i.args[0].try_into().unwrap();

if flags & 0xffafffff != 0 {
Expand All @@ -43,4 +131,59 @@ impl DmemManager {

todo!("sys_blockpool_open on new FS")
}

fn sys_blockpool_map(self: &Arc<Self>, _: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
let addr: usize = i.args[0].into();
let len: usize = i.args[1].into();
let mem_type: i32 = i.args[2].try_into().unwrap();
let protections: u32 = i.args[3].try_into().unwrap();
let flags: i32 = i.args[4].try_into().unwrap();

info!(
"sys_blockpool_map({}, {}, {}, {}, {})",
addr, len, mem_type, protections, flags
);

todo!()
}

fn sys_blockpool_unmap(self: &Arc<Self>, _: &VThread, _i: &SysIn) -> Result<SysOut, SysErr> {
todo!()
}

fn sys_blockpool_batch(self: &Arc<Self>, _: &VThread, _i: &SysIn) -> Result<SysOut, SysErr> {
todo!()
}

fn sys_blockpool_move(self: &Arc<Self>, _: &VThread, _i: &SysIn) -> Result<SysOut, SysErr> {
todo!()
}

fn get_dmem_device<'a>(self: &'a Arc<Self>, dmem: DmemContainer) -> &'a DmemDevice {
self.index(dmem)
}
}

impl Index<DmemContainer> for DmemManager {
type Output = DmemDevice;

fn index(&self, index: DmemContainer) -> &Self::Output {
match index {
DmemContainer::Zero => &self.dmem0,
DmemContainer::One => &self.dmem1,
DmemContainer::Two => &self.dmem2,
}
}
}

impl Into<SysOut> for DmemContainer {
fn into(self) -> SysOut {
(self as usize).into()
}
}

#[derive(Debug, Error)]
pub enum DmemManagerInitError {
#[error("couldn't create {0}")]
CreateDmemFailed(&'static str, #[source] MakeDevError),
}
1 change: 1 addition & 0 deletions src/kernel/src/fs/dev/cdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ bitflags! {
#[derive(Debug, Clone, Copy)]
pub struct DriverFlags: u32 {
const D_NEEDMINOR = 0x00800000;
const D_INIT = 0x80000000;
}
}

Expand Down
Loading

0 comments on commit 1cbc0ef

Please sign in to comment.