diff --git a/src/kernel/src/main.rs b/src/kernel/src/main.rs index f7b5ba8b5..978c58b68 100644 --- a/src/kernel/src/main.rs +++ b/src/kernel/src/main.rs @@ -1,7 +1,7 @@ use crate::arch::MachDep; use crate::budget::{Budget, BudgetManager, ProcType}; use crate::dev::{ - DebugManager, DebugManagerInitError, DipswInitError, DipswManager, TtyManager, + DebugManager, DebugManagerInitError, DipswInitError, DipswManager, DmemContainer, TtyManager, TtyManagerInitError, }; use crate::dmem::{DmemManager, DmemManagerInitError}; @@ -15,7 +15,7 @@ use crate::log::{print, LOGGER}; use crate::namedobj::NamedObjManager; use crate::net::NetManager; use crate::osem::OsemManager; -use crate::process::{ProcManager, VProc, VProcInitError, VThread}; +use crate::process::{ProcManager, VThread}; use crate::regmgr::RegMgr; use crate::rtld::{ExecError, LoadFlags, ModuleFlags, RuntimeLinker}; use crate::shm::SharedMemoryManager; @@ -364,7 +364,7 @@ fn run() -> Result<(), KernelError> { NamedObjManager::new(&mut syscalls); OsemManager::new(&mut syscalls); UmtxManager::new(&mut syscalls); - ProcManager::new(&mut syscalls); + let pmgr = ProcManager::new(&mut syscalls); // Initialize runtime linker. let ee = NativeEngine::new(); @@ -373,16 +373,17 @@ fn run() -> Result<(), KernelError> { // TODO: Get correct budget name from the PS4. let budget_id = budget.create(Budget::new("big app", ProcType::BigApp)); let proc_root = fs.lookup(proc_root, true, None).unwrap(); - - let proc = VProc::new( - auth, - budget_id, - ProcType::BigApp, - dev::DmemContainer::One, // See sys_budget_set on the PS4. - proc_root, - system_component, - syscalls, - )?; + let proc = pmgr + .spawn( + auth, + budget_id, + ProcType::BigApp, + DmemContainer::One, // See sys_budget_set on the PS4. + proc_root, + system_component, + syscalls, + ) + .map_err(KernelError::CreateProcessFailed)?; info!( "Application stack: {:p}:{:p}", @@ -611,8 +612,8 @@ enum KernelError { #[error("dmem manager initialization failed")] DmemManagerInitFailes(#[from] DmemManagerInitError), - #[error("virtual process initialization failed")] - VProcInitFailed(#[from] VProcInitError), + #[error("couldn't create application process")] + CreateProcessFailed(#[source] self::process::SpawnError), #[error("couldn't execute {0}")] ExecFailed(&'static VPath, #[source] ExecError), diff --git a/src/kernel/src/process/mod.rs b/src/kernel/src/process/mod.rs index 2137d36a6..2c07a4acb 100644 --- a/src/kernel/src/process/mod.rs +++ b/src/kernel/src/process/mod.rs @@ -1,6 +1,12 @@ +use crate::budget::ProcType; +use crate::dev::DmemContainer; +use crate::fs::Vnode; use crate::syscalls::Syscalls; +use crate::ucred::AuthInfo; +use crate::vm::MemoryManagerError; use std::sync::atomic::AtomicI32; use std::sync::Arc; +use thiserror::Error; pub use self::appinfo::*; pub use self::binary::*; @@ -33,6 +39,38 @@ impl ProcManager { pmgr } + + /// See `fork1` on the PS4 for a reference. + pub fn spawn( + &self, + auth: AuthInfo, + budget_id: usize, + budget_ptype: ProcType, + dmem_container: DmemContainer, + root: Arc, + system_path: impl Into, + mut sys: Syscalls, + ) -> Result, SpawnError> { + VProc::new( + auth, + budget_id, + budget_ptype, + dmem_container, + root, + system_path, + sys, + ) + } +} + +/// Represents an error when [`ProcManager::spawn()`] was failed. +#[derive(Debug, Error)] +pub enum SpawnError { + #[error("failed to load limits")] + FailedToLoadLimits(#[from] LoadLimitError), + + #[error("virtual memory initialization failed")] + VmInitFailed(#[from] MemoryManagerError), } static NEXT_ID: AtomicI32 = AtomicI32::new(123); diff --git a/src/kernel/src/process/proc.rs b/src/kernel/src/process/proc.rs index ee79cdfec..61f501734 100644 --- a/src/kernel/src/process/proc.rs +++ b/src/kernel/src/process/proc.rs @@ -1,6 +1,6 @@ use super::{ - AppInfo, Binaries, CpuLevel, CpuWhich, FileDesc, Limits, LoadLimitError, ResourceLimit, - ResourceType, SignalActs, VProcGroup, VSession, VThread, NEXT_ID, + AppInfo, Binaries, CpuLevel, CpuWhich, FileDesc, Limits, ResourceLimit, ResourceType, + SignalActs, SpawnError, VProcGroup, VSession, VThread, NEXT_ID, }; use crate::budget::ProcType; use crate::dev::DmemContainer; @@ -17,7 +17,7 @@ use crate::signal::{SigChldFlags, Signal}; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; use crate::sysent::ProcAbi; use crate::ucred::{AuthInfo, Gid, Privilege, Ucred, Uid}; -use crate::vm::{MemoryManagerError, Vm}; +use crate::vm::Vm; use bitflags::bitflags; use gmtx::{Gutex, GutexGroup, GutexReadGuard, GutexWriteGuard}; use macros::Errno; @@ -61,7 +61,7 @@ pub struct VProc { } impl VProc { - pub fn new( + pub(super) fn new( auth: AuthInfo, budget_id: usize, budget_ptype: ProcType, @@ -69,7 +69,7 @@ impl VProc { root: Arc, system_path: impl Into, mut sys: Syscalls, - ) -> Result, VProcInitError> { + ) -> Result, SpawnError> { let cred = if auth.caps.is_system() { // TODO: The groups will be copied from the parent process, which is SceSysCore. Ucred::new(Uid::ROOT, Uid::ROOT, vec![Gid::ROOT], auth) @@ -878,15 +878,5 @@ bitflags! { } } -/// Represents an error when [`VProc`] construction is failed. -#[derive(Debug, Error)] -pub enum VProcInitError { - #[error("failed to load limits")] - FailedToLoadLimits(#[from] LoadLimitError), - - #[error("virtual memory initialization failed")] - VmInitFailed(#[from] MemoryManagerError), -} - #[derive(Debug, Error, Errno)] pub enum CreateThreadError {}