From a85e51231d74ea1ee33ce5a34cd290768ad74dd9 Mon Sep 17 00:00:00 2001 From: Putta Khunchalee Date: Sun, 5 Nov 2023 17:07:39 +0700 Subject: [PATCH] Implements syscall 487 --- src/kernel/src/process/cpuset.rs | 25 ++++++++++ src/kernel/src/process/mod.rs | 81 ++++++++++++++++++++++++++++++-- src/kernel/src/process/thread.rs | 7 +++ src/kernel/src/syscalls/input.rs | 6 +++ src/kernel/src/ucred/auth.rs | 17 +++++++ 5 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 src/kernel/src/process/cpuset.rs diff --git a/src/kernel/src/process/cpuset.rs b/src/kernel/src/process/cpuset.rs new file mode 100644 index 000000000..2396c4e99 --- /dev/null +++ b/src/kernel/src/process/cpuset.rs @@ -0,0 +1,25 @@ +pub const CPU_LEVEL_WHICH: i32 = 3; +pub const CPU_WHICH_TID: i32 = 1; + +/// An implementation of `cpuset`. +#[derive(Debug)] +pub struct CpuSet { + mask: CpuMask, // cs_mask +} + +impl CpuSet { + pub fn new(mask: CpuMask) -> Self { + Self { mask } + } + + pub fn mask(&self) -> &CpuMask { + &self.mask + } +} + +/// An implementation of `cpuset_t`. +#[repr(C)] +#[derive(Debug, Default)] +pub struct CpuMask { + pub bits: [u64; 1], +} diff --git a/src/kernel/src/process/mod.rs b/src/kernel/src/process/mod.rs index 237cf9faa..3d8a0d014 100644 --- a/src/kernel/src/process/mod.rs +++ b/src/kernel/src/process/mod.rs @@ -1,4 +1,5 @@ pub use self::appinfo::*; +pub use self::cpuset::*; pub use self::file::*; pub use self::group::*; pub use self::rlimit::*; @@ -6,7 +7,7 @@ pub use self::session::*; pub use self::signal::*; pub use self::thread::*; -use crate::errno::{EINVAL, ENAMETOOLONG, EPERM, ESRCH}; +use crate::errno::{EINVAL, ENAMETOOLONG, EPERM, ERANGE, ESRCH}; use crate::idt::IdTable; use crate::info; use crate::signal::{ @@ -27,6 +28,7 @@ use std::sync::Arc; use thiserror::Error; mod appinfo; +mod cpuset; mod file; mod group; mod rlimit; @@ -51,7 +53,7 @@ pub struct VProc { objects: GroupMutex>>, app_info: AppInfo, ptc: u64, - uptc: AtomicPtr, // Use a unit type for minimum alignment. + uptc: AtomicPtr, mtxg: Arc, } @@ -63,7 +65,7 @@ impl VProc { let vp = Arc::new(Self { id: Self::new_id(), threads: mg.new_member(Vec::new()), - cred: Ucred::new(AuthInfo::EXE.clone()), + cred: Ucred::new(AuthInfo::SYS_CORE.clone()), group: mg.new_member(None), sigacts: mg.new_member(SignalActs::new()), files: VProcFiles::new(&mg), @@ -82,6 +84,7 @@ impl VProc { sys.register(416, &vp, Self::sys_sigaction); sys.register(432, &vp, Self::sys_thr_self); sys.register(466, &vp, Self::sys_rtprio_thread); + sys.register(487, &vp, Self::sys_cpuset_getaffinity); sys.register(557, &vp, Self::sys_namedobj_create); sys.register(585, &vp, Self::sys_is_in_sandbox); sys.register(587, &vp, Self::sys_get_authinfo); @@ -146,7 +149,7 @@ impl VProc { let mut threads = self.threads.write(); // TODO: Check how ucred is constructed for a thread. - let cred = Ucred::new(AuthInfo::EXE.clone()); + let cred = Ucred::new(AuthInfo::SYS_CORE.clone()); let td = Arc::new(VThread::new(Self::new_id(), cred, &self.mtxg)); let active = Box::new(ActiveThread { proc: self.clone(), @@ -419,6 +422,76 @@ impl VProc { Ok(SysOut::ZERO) } + fn sys_cpuset_getaffinity(self: &Arc, i: &SysIn) -> Result { + // Get arguments. + let level: i32 = i.args[0].try_into().unwrap(); + let which: i32 = i.args[1].try_into().unwrap(); + let id: i64 = i.args[2].into(); + let cpusetsize: usize = i.args[3].into(); + let mask: *mut u8 = i.args[4].into(); + + // TODO: Refactor this for readability. + if cpusetsize.wrapping_sub(8) > 8 { + return Err(SysErr::Raw(ERANGE)); + } + + let ttd = self.cpuset_which(which, id)?; + let mut buf = vec![0u8; cpusetsize]; + + match level { + CPU_LEVEL_WHICH => match which { + CPU_WHICH_TID => { + let v = ttd.cpuset().mask().bits[0].to_ne_bytes(); + buf[..v.len()].copy_from_slice(&v); + } + v => todo!("sys_cpuset_getaffinity with which = {v}"), + }, + v => todo!("sys_cpuset_getaffinity with level = {v}"), + } + + // TODO: What is this? + let x = u32::from_ne_bytes(buf[..4].try_into().unwrap()); + let y = (x >> 1 & 0x55) + (x & 0x55) * 2; + let z = (y >> 2 & 0xfffffff3) + (y & 0x33) * 4; + + unsafe { + std::ptr::write_unaligned::( + buf.as_mut_ptr() as _, + (z >> 4 | (z & 0xf) << 4) as u64, + ); + + std::ptr::copy_nonoverlapping(buf.as_ptr(), mask, cpusetsize); + } + + Ok(SysOut::ZERO) + } + + /// See `cpuset_which` on the PS4 for a reference. + fn cpuset_which(&self, which: i32, id: i64) -> Result, SysErr> { + let td = match which { + CPU_WHICH_TID => { + if id == -1 { + todo!("cpuset_which with id = -1"); + } else { + let threads = self.threads.read(); + let td = threads.iter().find(|t| t.id().get() == id as i32).cloned(); + + if td.is_none() { + return Err(SysErr::Raw(ESRCH)); + } + + td + } + } + v => todo!("cpuset_which with which = {v}"), + }; + + match td { + Some(v) => Ok(v), + None => todo!("cpuset_which with td = NULL"), + } + } + // TODO: This should not be here. fn sys_namedobj_create(self: &Arc, i: &SysIn) -> Result { // Get arguments. diff --git a/src/kernel/src/process/thread.rs b/src/kernel/src/process/thread.rs index 11a4c20d9..88c347a26 100644 --- a/src/kernel/src/process/thread.rs +++ b/src/kernel/src/process/thread.rs @@ -1,3 +1,4 @@ +use super::{CpuMask, CpuSet}; use crate::signal::SignalSet; use crate::ucred::{Privilege, PrivilegeError, Ucred}; use bitflags::bitflags; @@ -18,6 +19,7 @@ pub struct VThread { pri_class: u16, // td_pri_class base_user_pri: u16, // td_base_user_pri pcb: GroupMutex, // td_pcb + cpuset: CpuSet, // td_cpuset } impl VThread { @@ -33,6 +35,7 @@ impl VThread { fsbase: 0, flags: PcbFlags::empty(), }), + cpuset: CpuSet::new(CpuMask::default()), // TODO: Same here. } } @@ -70,6 +73,10 @@ impl VThread { self.pcb.write() } + pub fn cpuset(&self) -> &CpuSet { + &self.cpuset + } + /// An implementation of `priv_check`. pub fn priv_check(&self, p: Privilege) -> Result<(), PrivilegeError> { self.cred.priv_check(p) diff --git a/src/kernel/src/syscalls/input.rs b/src/kernel/src/syscalls/input.rs index 7fc66292c..6e41a971c 100644 --- a/src/kernel/src/syscalls/input.rs +++ b/src/kernel/src/syscalls/input.rs @@ -78,6 +78,12 @@ impl From for *mut T { } } +impl From for i64 { + fn from(v: SysArg) -> Self { + v.0 as _ + } +} + impl From for u64 { fn from(v: SysArg) -> Self { v.0 as _ diff --git a/src/kernel/src/ucred/auth.rs b/src/kernel/src/ucred/auth.rs index 2bd18afe0..043604ca1 100644 --- a/src/kernel/src/ucred/auth.rs +++ b/src/kernel/src/ucred/auth.rs @@ -9,6 +9,23 @@ pub struct AuthInfo { } impl AuthInfo { + pub const SYS_CORE: Self = Self { + paid: 0x3800000000000007, + caps: [ + 0x40001C0000000000, + 0x800000000000FF00, + 0x0000000000000000, + 0x0000000000000000, + ], + attrs: [ + 0x4000400080000000, + 0x8000000000000000, + 0x0800000000000000, + 0xF0000000FFFF4000, + ], + unk: [0; 0x40], + }; + pub const EXE: Self = Self { paid: 0x3100000000000001, caps: [