From 5bdc59ec6b426963fa7222ac6280af47b893c0ab Mon Sep 17 00:00:00 2001 From: Putta Khunchalee Date: Wed, 25 Oct 2023 17:27:00 +0700 Subject: [PATCH] Implements sysctl kern.proc.ptc and kern.sched.cpusetsize (#410) --- src/kernel/src/budget/mod.rs | 39 +++++++++++++++++++ src/kernel/src/main.rs | 7 +++- src/kernel/src/memory/page.rs | 4 -- src/kernel/src/process/mod.rs | 29 +++++++------- src/kernel/src/sysctl/mod.rs | 72 ++++++++++++++++++++++++++++++++++- 5 files changed, 129 insertions(+), 22 deletions(-) create mode 100644 src/kernel/src/budget/mod.rs diff --git a/src/kernel/src/budget/mod.rs b/src/kernel/src/budget/mod.rs new file mode 100644 index 000000000..fc88ddf44 --- /dev/null +++ b/src/kernel/src/budget/mod.rs @@ -0,0 +1,39 @@ +use crate::errno::{ENOENT, ENOSYS, ESRCH}; +use crate::info; +use crate::process::{VProc, VThread}; +use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; +use std::sync::Arc; + +/// An implementation of budget system on the PS4. +pub struct Budget { + vp: Arc, +} + +impl Budget { + pub fn new(vp: &Arc, sys: &mut Syscalls) -> Arc { + let budget = Arc::new(Self { vp: vp.clone() }); + + sys.register(610, &budget, Self::sys_budget_get_ptype); + + budget + } + + fn sys_budget_get_ptype(self: &Arc, i: &SysIn) -> Result { + // Check if PID is our process. + let pid: i32 = i.args[0].try_into().unwrap(); + let td = VThread::current(); + + info!("Getting budget process type for process {pid}."); + + if td.cred().is_system() || pid == -1 || pid == self.vp.id().get() { + if pid == -1 || pid == self.vp.id().get() { + // TODO: Invoke id_rlock. Not sure why return ENOENT is working here. + Err(SysErr::Raw(ENOENT)) + } else { + Err(SysErr::Raw(ESRCH)) + } + } else { + Err(SysErr::Raw(ENOSYS)) + } + } +} diff --git a/src/kernel/src/main.rs b/src/kernel/src/main.rs index 4a67c22ad..781dbfbfb 100644 --- a/src/kernel/src/main.rs +++ b/src/kernel/src/main.rs @@ -1,5 +1,6 @@ use crate::arch::MachDep; use crate::arnd::Arnd; +use crate::budget::Budget; use crate::ee::{EntryArg, RawFn}; use crate::fs::Fs; use crate::llvm::Llvm; @@ -22,6 +23,7 @@ use std::sync::Arc; mod arch; mod arnd; +mod budget; mod console; mod ee; mod errno; @@ -123,10 +125,10 @@ fn main() -> ExitCode { let mut log = info!(); - writeln!(log, "Page size : {}", mm.page_size()).unwrap(); + writeln!(log, "Page size : {:#x}", mm.page_size()).unwrap(); writeln!( log, - "Allocation granularity: {}", + "Allocation granularity: {:#x}", mm.allocation_granularity() ) .unwrap(); @@ -185,6 +187,7 @@ fn run( let fs = Fs::new(root, app, vp, &mut syscalls); RegMgr::new(&mut syscalls); MachDep::new(&mut syscalls); + Budget::new(vp, &mut syscalls); // Initialize runtime linker. info!("Initializing runtime linker."); diff --git a/src/kernel/src/memory/page.rs b/src/kernel/src/memory/page.rs index a8f436cc8..fa83fffd4 100644 --- a/src/kernel/src/memory/page.rs +++ b/src/kernel/src/memory/page.rs @@ -16,10 +16,6 @@ impl<'a> VPages<'a> { self.ptr as _ } - pub fn len(&self) -> usize { - self.len - } - pub fn end(&self) -> *const u8 { unsafe { self.ptr.add(self.len) } } diff --git a/src/kernel/src/process/mod.rs b/src/kernel/src/process/mod.rs index e1da909d6..237cf9faa 100644 --- a/src/kernel/src/process/mod.rs +++ b/src/kernel/src/process/mod.rs @@ -6,7 +6,7 @@ pub use self::session::*; pub use self::signal::*; pub use self::thread::*; -use crate::errno::{EINVAL, ENAMETOOLONG, ENOENT, ENOSYS, EPERM, ESRCH}; +use crate::errno::{EINVAL, ENAMETOOLONG, EPERM, ESRCH}; use crate::idt::IdTable; use crate::info; use crate::signal::{ @@ -20,6 +20,8 @@ use llt::{SpawnError, Thread}; use std::any::Any; use std::mem::zeroed; use std::num::NonZeroI32; +use std::ptr::null_mut; +use std::sync::atomic::AtomicPtr; use std::sync::atomic::{AtomicI32, Ordering}; use std::sync::Arc; use thiserror::Error; @@ -48,6 +50,8 @@ pub struct VProc { limits: [ResourceLimit; ResourceLimit::NLIMITS], // p_limit objects: GroupMutex>>, app_info: AppInfo, + ptc: u64, + uptc: AtomicPtr, // Use a unit type for minimum alignment. mtxg: Arc, } @@ -66,6 +70,8 @@ impl VProc { objects: mg.new_member(IdTable::new(0x1000)), limits, app_info: AppInfo::new(), + ptc: 0, + uptc: AtomicPtr::new(null_mut()), mtxg: mg, }); @@ -79,7 +85,6 @@ impl VProc { 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); - sys.register(610, &vp, Self::sys_budget_get_ptype); Ok(vp) } @@ -108,6 +113,14 @@ impl VProc { &self.app_info } + pub fn ptc(&self) -> u64 { + self.ptc + } + + pub fn uptc(&self) -> &AtomicPtr { + &self.uptc + } + pub fn mutex_group(&self) -> &Arc { &self.mtxg } @@ -478,18 +491,6 @@ impl VProc { Ok(SysOut::ZERO) } - fn sys_budget_get_ptype(self: &Arc, i: &SysIn) -> Result { - // Check if PID is our process. - let pid: i32 = i.args[0].try_into().unwrap(); - - if pid != -1 && pid != self.id.get() { - return Err(SysErr::Raw(ENOSYS)); - } - - // TODO: Invoke id_rlock. Not sure why return ENOENT is working here. - Err(SysErr::Raw(ENOENT)) - } - fn new_id() -> NonZeroI32 { let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); diff --git a/src/kernel/src/sysctl/mod.rs b/src/kernel/src/sysctl/mod.rs index e95f6c5d1..33aee811c 100644 --- a/src/kernel/src/sysctl/mod.rs +++ b/src/kernel/src/sysctl/mod.rs @@ -5,6 +5,8 @@ use crate::process::VProc; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; use std::any::Any; use std::cmp::min; +use std::ptr::null_mut; +use std::sync::atomic::Ordering; use std::sync::Arc; /// A registry of system parameters. @@ -316,6 +318,26 @@ impl Sysctl { Ok(()) } + fn kern_proc_ptc( + &self, + _: &'static Oid, + _: &Arg, + _: usize, + req: &mut SysctlReq, + ) -> Result<(), SysErr> { + req.write(&self.vp.ptc().to_ne_bytes())?; + + self.vp.uptc().store( + req.old + .as_mut() + .map(|v| v.as_mut_ptr()) + .unwrap_or(null_mut()), + Ordering::Relaxed, + ); + + Ok(()) + } + fn kern_usrstack( &self, _: &'static Oid, @@ -527,7 +549,7 @@ static KERN_PROC_CHILDREN: OidList = OidList { static KERN_PROC_APPINFO: Oid = Oid { parent: &KERN_PROC_CHILDREN, - link: None, // TODO: Implement this. + link: Some(&KERN_PROC_PTC), // TODO: Use a proper value. number: Sysctl::KERN_PROC_APPINFO, kind: 0xC0040001, arg1: None, // TODO: This value on the PS4 is not null. @@ -539,6 +561,20 @@ static KERN_PROC_APPINFO: Oid = Oid { enabled: true, }; +static KERN_PROC_PTC: Oid = Oid { + parent: &KERN_PROC_CHILDREN, + link: None, // TODO: Implement this. + number: 0x2B, + kind: 0x90040009, + arg1: None, + arg2: 0, + name: "ptc", + handler: Some(Sysctl::kern_proc_ptc), + fmt: "LU", + descr: "Process time counter", + enabled: true, +}; + static KERN_USRSTACK: Oid = Oid { parent: &KERN_CHILDREN, link: Some(&KERN_ARANDOM), // TODO: Use a proper value. @@ -555,7 +591,7 @@ static KERN_USRSTACK: Oid = Oid { static KERN_ARANDOM: Oid = Oid { parent: &KERN_CHILDREN, - link: Some(&KERN_SMP), // TODO: Use a proper value. + link: Some(&KERN_SCHED), // TODO: Use a proper value. number: Sysctl::KERN_ARND, kind: 0x80048005, arg1: None, @@ -567,6 +603,38 @@ static KERN_ARANDOM: Oid = Oid { enabled: true, }; +static KERN_SCHED: Oid = Oid { + parent: &KERN_CHILDREN, + link: Some(&KERN_SMP), // TODO: Use a proper value. + number: 0x2A0, + kind: 0xC0000001, + arg1: Some(&KERN_SCHED_CHILDREN), + arg2: 0, + name: "sched", + handler: None, + fmt: "N", + descr: "Scheduler", + enabled: false, +}; + +static KERN_SCHED_CHILDREN: OidList = OidList { + first: Some(&KERN_SCHED_CPUSETSIZE), // TODO: Use a proper value. +}; + +static KERN_SCHED_CPUSETSIZE: Oid = Oid { + parent: &KERN_SCHED_CHILDREN, + link: None, + number: 0x4E4, + kind: 0x80040002, + arg1: None, + arg2: 8, + name: "cpusetsize", + handler: Some(Sysctl::handle_int), + fmt: "I", + descr: "sizeof(cpuset_t)", + enabled: true, +}; + static KERN_SMP: Oid = Oid { parent: &KERN_CHILDREN, link: None, // TODO: Implement this.