Skip to content

Commit

Permalink
Moves syscall table to p_sysent (#784)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Mar 31, 2024
1 parent 7b975ec commit cad411f
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 63 deletions.
21 changes: 9 additions & 12 deletions src/kernel/src/ee/native/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::fs::{VPath, VPathBuf};
use crate::process::VThread;
use crate::rtld::{CodeWorkspaceError, Memory, Module, UnprotectSegmentError};
use crate::syscalls::{SysIn, SysOut, Syscalls};
use crate::syscalls::{SysIn, SysOut};
use crate::vm::Protections;
use byteorder::{ByteOrder, LE};
use iced_x86::code_asm::{
Expand All @@ -11,13 +11,12 @@ use iced_x86::code_asm::{
use iced_x86::{Code, Decoder, DecoderOptions, Instruction, OpKind, Register};
use std::any::Any;
use std::mem::{size_of, transmute};
use std::sync::{Arc, OnceLock};
use std::sync::Arc;
use thiserror::Error;

/// An implementation of [`ExecutionEngine`] for running the PS4 binary natively.
#[derive(Debug)]
pub struct NativeEngine {
syscalls: OnceLock<Syscalls>,
xsave_area: i32,
}

Expand All @@ -31,14 +30,7 @@ impl NativeEngine {

assert!(xsave_area > 0);

Arc::new(Self {
syscalls: OnceLock::new(),
xsave_area,
})
}

pub fn set_syscalls(&self, v: Syscalls) {
self.syscalls.set(v).unwrap();
Arc::new(Self { xsave_area })
}

pub fn setup_module(self: &Arc<Self>, md: &mut Module) -> Result<(), SetupModuleError> {
Expand Down Expand Up @@ -448,7 +440,12 @@ impl NativeEngine {
/// # Safety
/// This method cannot be called from Rust.
unsafe extern "sysv64" fn syscall(&self, i: &SysIn, o: &mut SysOut) -> i64 {
self.syscalls.get().unwrap().exec(i, o)
VThread::current()
.unwrap()
.proc()
.abi()
.syscalls()
.exec(i, o)
}

/// # Safety
Expand Down
24 changes: 11 additions & 13 deletions src/kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ mod shm;
mod signal;
mod syscalls;
mod sysctl;
mod sysent;
mod time;
mod ucred;
mod umtx;
Expand Down Expand Up @@ -356,6 +357,15 @@ fn run() -> Result<(), KernelError> {
TimeManager::new(&mut syscalls);
KernelQueueManager::new(&mut syscalls);
NetManager::new(&mut syscalls);
NamedObjManager::new(&mut syscalls);
OsemManager::new(&mut syscalls);
UmtxManager::new(&mut syscalls);

// Initialize runtime linker.
info!("Initializing runtime linker.");

let ee = NativeEngine::new();
let ld = RuntimeLinker::new(&fs, &ee, &mut syscalls);

// TODO: Get correct budget name from the PS4.
let budget_id = budget.create(Budget::new("big app", ProcType::BigApp));
Expand All @@ -367,7 +377,7 @@ fn run() -> Result<(), KernelError> {
1, // See sys_budget_set on the PS4.
root,
"QXuNNl0Zhn",
&mut syscalls,
syscalls,
)?;

info!(
Expand All @@ -376,18 +386,6 @@ fn run() -> Result<(), KernelError> {
proc.vm().stack().end()
);

NamedObjManager::new(&mut syscalls, &proc);
OsemManager::new(&mut syscalls, &proc);
UmtxManager::new(&mut syscalls);

// Initialize runtime linker.
info!("Initializing runtime linker.");

let ee = NativeEngine::new();
let ld = RuntimeLinker::new(&fs, &ee, &mut syscalls);

ee.set_syscalls(syscalls);

// TODO: Check if this credential is actually correct for game main thread.
let cred = Arc::new(Ucred::new(
Uid::ROOT,
Expand Down
24 changes: 10 additions & 14 deletions src/kernel/src/namedobj/mod.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
use crate::{
errno::EINVAL,
idt::Entry,
info,
process::{VProc, VThread},
syscalls::{SysErr, SysIn, SysOut, Syscalls},
};
use crate::errno::EINVAL;
use crate::idt::Entry;
use crate::info;
use crate::process::VThread;
use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls};
use std::sync::Arc;

pub struct NamedObjManager {
proc: Arc<VProc>,
}
pub struct NamedObjManager {}

impl NamedObjManager {
pub fn new(sys: &mut Syscalls, proc: &Arc<VProc>) -> Arc<Self> {
let namedobj = Arc::new(Self { proc: proc.clone() });
pub fn new(sys: &mut Syscalls) -> Arc<Self> {
let namedobj = Arc::new(Self {});

sys.register(557, &namedobj, Self::sys_namedobj_create);

namedobj
}

fn sys_namedobj_create(self: &Arc<Self>, _: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
fn sys_namedobj_create(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
// Get arguments.
let name = unsafe { i.args[0].to_str(32) }?.ok_or(SysErr::Raw(EINVAL))?;
let data: usize = i.args[1].into();
let flags: u32 = i.args[2].try_into().unwrap();

// Allocate the entry.
let mut table = self.proc.objects_mut();
let mut table = td.proc().objects_mut();

let obj = NamedObj::new(name, data);

Expand Down
13 changes: 5 additions & 8 deletions src/kernel/src/osem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,21 @@ use crate::errno::EINVAL;
use crate::idt::Entry;
use crate::process::VThread;
use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls};
use crate::VProc;
use bitflags::bitflags;
use std::sync::Arc;

pub struct OsemManager {
proc: Arc<VProc>,
}
pub struct OsemManager {}

impl OsemManager {
pub fn new(sys: &mut Syscalls, proc: &Arc<VProc>) -> Arc<Self> {
let osem = Arc::new(Self { proc: proc.clone() });
pub fn new(sys: &mut Syscalls) -> Arc<Self> {
let osem = Arc::new(Self {});

sys.register(549, &osem, Self::sys_osem_create);

osem
}

fn sys_osem_create(self: &Arc<Self>, _: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
fn sys_osem_create(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
let name = unsafe { i.args[0].to_str(32) }?.unwrap();
let flags = {
let flags = i.args[1].try_into().unwrap();
Expand All @@ -36,7 +33,7 @@ impl OsemManager {
flags
};

let mut objects = self.proc.objects_mut();
let mut objects = td.proc().objects_mut();

let id = objects
.alloc_infallible(|_| Entry::new(Some(name.to_owned()), Osem::new(flags), 0x120));
Expand Down
16 changes: 13 additions & 3 deletions src/kernel/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::signal::{
};
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 gmtx::{Gutex, GutexGroup, GutexReadGuard, GutexWriteGuard};
Expand All @@ -23,7 +24,7 @@ use std::num::NonZeroI32;
use std::ptr::null;
use std::ptr::null_mut;
use std::sync::atomic::{AtomicI32, AtomicPtr, Ordering};
use std::sync::Arc;
use std::sync::{Arc, OnceLock};
use thiserror::Error;

pub use self::appinfo::*;
Expand Down Expand Up @@ -56,6 +57,7 @@ pub struct VProc {
threads: Gutex<Vec<Arc<VThread>>>, // p_threads
cred: Ucred, // p_ucred
group: Gutex<Option<VProcGroup>>, // p_pgrp
abi: OnceLock<ProcAbi>, // p_sysent
vm: Arc<Vm>, // p_vmspace
sigacts: Gutex<SignalActs>, // p_sigacts
files: Arc<FileDesc>, // p_fd
Expand All @@ -80,7 +82,7 @@ impl VProc {
dmem_container: usize,
root: Arc<Vnode>,
system_path: impl Into<String>,
sys: &mut Syscalls,
mut sys: Syscalls,
) -> Result<Arc<Self>, VProcInitError> {
let cred = if auth.caps.is_system() {
// TODO: The groups will be copied from the parent process, which is SceSysCore.
Expand All @@ -98,7 +100,8 @@ impl VProc {
threads: gg.spawn(Vec::new()),
cred,
group: gg.spawn(None),
vm: Vm::new(sys)?,
abi: OnceLock::new(),
vm: Vm::new(&mut sys)?,
sigacts: gg.spawn(SignalActs::new()),
files: FileDesc::new(root),
system_path: system_path.into(),
Expand All @@ -114,6 +117,7 @@ impl VProc {
uptc: AtomicPtr::new(null_mut()),
});

// TODO: Move all syscalls here to somewhere else.
sys.register(20, &vp, Self::sys_getpid);
sys.register(50, &vp, Self::sys_setlogin);
sys.register(147, &vp, Self::sys_setsid);
Expand All @@ -129,6 +133,8 @@ impl VProc {
sys.register(587, &vp, Self::sys_get_authinfo);
sys.register(602, &vp, Self::sys_randomized_path);

vp.abi.set(ProcAbi::new(sys)).unwrap();

Ok(vp)
}

Expand All @@ -140,6 +146,10 @@ impl VProc {
&self.cred
}

pub fn abi(&self) -> &ProcAbi {
self.abi.get().unwrap()
}

pub fn vm(&self) -> &Arc<Vm> {
&self.vm
}
Expand Down
1 change: 1 addition & 0 deletions src/kernel/src/rtld/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ impl RuntimeLinker {
0
};

// TODO: Check exec_new_vmspace on the PS4 to see what we have missed here.
// TODO: Apply remaining checks from exec_self_imgact.
// Map eboot.bin.
let mut app = Module::map(
Expand Down
17 changes: 17 additions & 0 deletions src/kernel/src/sysent/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::syscalls::Syscalls;

/// Implementation of `sysentvec` structure.
#[derive(Debug)]
pub struct ProcAbi {
syscalls: Syscalls, // sv_size + sv_table
}

impl ProcAbi {
pub fn new(syscalls: Syscalls) -> Self {
Self { syscalls }
}

pub fn syscalls(&self) -> &Syscalls {
&self.syscalls
}
}
14 changes: 1 addition & 13 deletions src/kernel/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ mod storage;
/// Implementation of `vmspace` structure.
#[derive(Debug)]
pub struct Vm {
page_size: usize,
allocation_granularity: usize,
allocations: RwLock<BTreeMap<usize, Alloc>>, // Key is Alloc::addr.
stack: AppStack,
Expand All @@ -35,6 +34,7 @@ impl Vm {
/// Size of a memory page on PS4.
pub const VIRTUAL_PAGE_SIZE: usize = 0x4000;

/// See `vmspace_alloc` on the PS4 for a reference.
pub fn new(sys: &mut Syscalls) -> Result<Arc<Self>, MemoryManagerError> {
// Check if page size on the host is supported. We don't need to check allocation
// granularity because it is always multiply by page size, which is a correct value.
Expand All @@ -49,9 +49,7 @@ impl Vm {
return Err(MemoryManagerError::UnsupportedPageSize);
}

// TODO: Check exec_new_vmspace on the PS4 to see what we have missed here.
let mut mm = Self {
page_size,
allocation_granularity,
allocations: RwLock::default(),
stack: AppStack::new(),
Expand Down Expand Up @@ -91,16 +89,6 @@ impl Vm {
Ok(mm)
}

/// Gets size of page on the host system.
pub fn page_size(&self) -> usize {
self.page_size
}

/// Gets allocation granularity on the host system.
pub fn allocation_granularity(&self) -> usize {
self.allocation_granularity
}

pub fn stack(&self) -> &AppStack {
&self.stack
}
Expand Down

0 comments on commit cad411f

Please sign in to comment.