Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initializes kick_pagedaemons implementation #1288

Merged
merged 2 commits into from
Feb 22, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion kernel/src/event/ty.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,12 @@ pub trait EventType: 'static {
type Wrapper: Send + Sync + 'static;
}

impl<A: 'static> EventType for for<'a> fn(&'a mut A) {
impl<A: 'static> EventType for fn(&A) {
type Handler<S: Subsystem> = fn(&Arc<S>, &A);
type Wrapper = Box<dyn Fn(&A) + Send + Sync>;
}

impl<A: 'static> EventType for fn(&mut A) {
type Handler<S: Subsystem> = fn(&Arc<S>, &mut A);
type Wrapper = Box<dyn Fn(&mut A) + Send + Sync>;
}
10 changes: 5 additions & 5 deletions kernel/src/main.rs
Original file line number Diff line number Diff line change
@@ -62,10 +62,10 @@ fn setup() -> ContextSetup {
// then loop the list to execute all of it. We manually execute those functions instead for
// readability. This also allow us to pass data from one function to another function. See
// mi_startup function on the Orbis for a reference.
let uma = init_vm(); // 161 on PS4 11.00.
let pmgr = ProcMgr::new();
let procs = ProcMgr::new();
let uma = init_vm(&procs); // 161 on PS4 11.00.

ContextSetup { uma, pmgr }
ContextSetup { uma, pmgr: procs }
}

fn run() -> ! {
@@ -85,8 +85,8 @@ fn run() -> ! {
/// | Version | Offset |
/// |---------|--------|
/// |PS4 11.00|0x39A390|
fn init_vm() -> Arc<Uma> {
let vm = Vm::new();
fn init_vm(procs: &Arc<ProcMgr>) -> Arc<Uma> {
let vm = Vm::new(procs);

Uma::new(vm)
}
20 changes: 20 additions & 0 deletions kernel/src/proc/mod.rs
Original file line number Diff line number Diff line change
@@ -22,19 +22,28 @@ mod thread;
/// Manage all processes in the system.
pub struct ProcMgr {
procs: Mutex<HashMap<Pid, Weak<Proc>>>, // allproc + pidhashtbl + zombproc
pagers: [Weak<Proc>; 2], // pageproc
events: Arc<EventSet<ProcEvents>>,
}

impl ProcMgr {
pub fn new() -> Arc<Self> {
let pagers = Self::spawn_pagers();
let events = Arc::default();

Arc::new(Self {
procs: Mutex::new(HashMap::new()),
pagers,
events,
})
}

/// # Panics
/// If `i` is not valid.
pub fn pager(&self, i: usize) -> &Weak<Proc> {
&self.pagers[i]
}

pub fn list(&self) -> MappedMutex<impl ExactSizeIterator<Item = &Weak<Proc>> + '_> {
MutexGuard::map(self.procs.lock(), |procs| procs.values())
}
@@ -58,6 +67,16 @@ impl ProcMgr {
// Create process.
Ok(Proc::new(abi, &self.events))
}

/// See `kick_pagedaemons` on the Orbis for a reference.
///
/// # Reference offsets
/// | Version | Offset |
/// |---------|--------|
/// |PS4 11.00|0x3E0E40|
fn spawn_pagers() -> [Weak<Proc>; 2] {
todo!()
}
}

impl Subsystem for ProcMgr {}
@@ -66,6 +85,7 @@ impl Subsystem for ProcMgr {}
#[derive(Default)]
pub struct ProcEvents {
pub process_init: Event<fn(&mut Proc)>,
pub process_ctor: Event<fn(&Weak<Proc>)>,
}

/// Flags to control behavior of [`ProcMgr::fork()`].
32 changes: 30 additions & 2 deletions kernel/src/proc/process.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
use super::{ProcAbi, ProcEvents};
use crate::event::EventSet;
use alloc::sync::Arc;
use core::sync::atomic::{AtomicUsize, Ordering};

/// Implementation of `proc` structure.
pub struct Proc {
abi: Arc<dyn ProcAbi>, // p_sysent
pager: AtomicUsize,
}

impl Proc {
/// See `proc_init` and `proc_ctor` on the Orbis for a reference.
///
/// # Reference offsets
/// | Version | Offset |
/// |---------|---------------------|
/// |PS4 11.00|0x375970 and 0x3755D0|
pub fn new(abi: Arc<dyn ProcAbi>, events: &Arc<EventSet<ProcEvents>>) -> Arc<Self> {
let mut proc = Self { abi };
let mut proc = Self {
abi,
pager: AtomicUsize::new(0),
};

// Trigger process_init event.
let mut et = events.trigger();
@@ -18,6 +29,16 @@ impl Proc {
h(&mut proc);
}

// Trigger process_ctor event.
let proc = Arc::new(proc);
let weak = Arc::downgrade(&proc);

for h in et.select(|s| &s.process_ctor) {
h(&weak);
}

drop(et);

todo!()
}

@@ -28,10 +49,17 @@ impl Proc {
/// # Context safety
/// This function does not require a CPU context.
pub fn new_bare(abi: Arc<dyn ProcAbi>) -> Self {
Self { abi }
Self {
abi,
pager: AtomicUsize::new(0),
}
}

pub fn abi(&self) -> &Arc<dyn ProcAbi> {
&self.abi
}

pub fn pager(&self) -> usize {
self.pager.load(Ordering::Relaxed)
}
}
3 changes: 2 additions & 1 deletion kernel/src/uma/aarch64.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::Alloc;
use crate::vm::Vm;

pub fn small_alloc(vm: &Vm) {
pub fn small_alloc(vm: &Vm, flags: Alloc) {
todo!()
}
30 changes: 18 additions & 12 deletions kernel/src/uma/keg.rs
Original file line number Diff line number Diff line change
@@ -11,14 +11,14 @@ use core::num::NonZero;
/// Implementation of `uma_keg` structure.
pub struct UmaKeg {
vm: Arc<Vm>,
size: NonZero<usize>, // uk_size
ipers: usize, // uk_ipers
alloc: fn(&Vm), // uk_allocf
max_pages: u32, // uk_maxpages
pages: u32, // uk_pages
free: u32, // uk_free
recurse: u32, // uk_recurse
flags: UmaFlags, // uk_flags
size: NonZero<usize>, // uk_size
ipers: usize, // uk_ipers
alloc: fn(&Vm, Alloc), // uk_allocf
max_pages: u32, // uk_maxpages
pages: u32, // uk_pages
free: u32, // uk_free
recurse: u32, // uk_recurse
flags: UmaFlags, // uk_flags
}

impl UmaKeg {
@@ -217,7 +217,7 @@ impl UmaKeg {
}

self.recurse += 1;
self.alloc_slab();
self.alloc_slab(flags);
self.recurse -= 1;

todo!()
@@ -232,11 +232,17 @@ impl UmaKeg {
/// | Version | Offset |
/// |---------|--------|
/// |PS4 11.00|0x13FBA0|
fn alloc_slab(&self) {
fn alloc_slab(&self, flags: Alloc) {
if self.flags.has(UmaFlags::Offpage) {
todo!()
} else {
(self.alloc)(&self.vm);
let flags = if self.flags.has(UmaFlags::Malloc) {
flags & !Alloc::Zero
} else {
flags | Alloc::Zero
};

(self.alloc)(&self.vm, flags);
todo!()
}
}
@@ -247,7 +253,7 @@ impl UmaKeg {
/// | Version | Offset |
/// |---------|--------|
/// |PS4 11.00|0x1402F0|
fn page_alloc(_: &Vm) {
fn page_alloc(_: &Vm, _: Alloc) {
todo!()
}
}
11 changes: 9 additions & 2 deletions kernel/src/uma/x86_64.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::Alloc;
use crate::vm::Vm;

/// See `uma_small_alloc` on the Orbis for a reference.
@@ -6,9 +7,15 @@ use crate::vm::Vm;
/// | Version | Offset |
/// |---------|--------|
/// |PS4 11.00|0x22FD70|
pub fn small_alloc(vm: &Vm) {
pub fn small_alloc(vm: &Vm, flags: Alloc) {
// TODO: There are an increment on an unknown variable on the Orbis.
vm.alloc_page(None);
vm.alloc_page(
None,
// TODO: Refactor this for readability.
((((u32::from(flags) & 0x100) >> 2) - (u32::from((u32::from(flags) & 0x401) == 1)) + 0x22)
| 0x100)
.into(),
);

todo!()
}
27 changes: 23 additions & 4 deletions kernel/src/vm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
pub use self::object::*;

use self::stats::VmStats;
use crate::context::current_thread;
use crate::lock::GutexGroup;
use crate::proc::ProcMgr;
use alloc::sync::Arc;
use macros::bitflag;

mod object;
mod stats;

/// Implementation of Virtual Memory system.
pub struct Vm {
procs: Arc<ProcMgr>,
stats: [VmStats; 3],
}

impl Vm {
pub fn new() -> Arc<Self> {
pub fn new(procs: &Arc<ProcMgr>) -> Arc<Self> {
// Initializes stats. The Orbis initialize these data in vm_pageout function but it is
// possible for data race.
let pageout_page_count = 0x10; // TODO: Figure out where this value come from.
@@ -37,7 +41,10 @@ impl Vm {
},
];

Arc::new(Self { stats })
Arc::new(Self {
procs: procs.clone(),
stats,
})
}

/// See `vm_page_alloc` on the Orbis for a reference.
@@ -46,21 +53,33 @@ impl Vm {
/// | Version | Offset |
/// |---------|--------|
/// |PS4 11.00|0x02B030|
pub fn alloc_page(&self, obj: Option<VmObject>) {
pub fn alloc_page(&self, obj: Option<VmObject>, _: VmAlloc) {
// Get target VM.
let vm = match obj {
Some(_) => todo!(),
None => 0,
};

let td = current_thread();
let stats = &self.stats[vm];
let cache_count = stats.cache_count.read();
let free_count = stats.free_count.read();

if *cache_count + *free_count <= stats.free_reserved {
todo!()
// Page daemon should never die so we use unwrap to catch that here.
let p = td.proc();

if Arc::ptr_eq(p, &self.procs.pager(p.pager()).upgrade().unwrap()) {
todo!()
} else {
todo!()
}
}

todo!()
}
}

/// Flags for [`Vm::alloc_page()`].
#[bitflag(u32)]
pub enum VmAlloc {}
2 changes: 0 additions & 2 deletions legacy/src/process/mod.rs
Original file line number Diff line number Diff line change
@@ -61,7 +61,6 @@ pub struct ProcManager {
proc0: Arc<VProc>, // proc0
thread0: Arc<VThread>, // thread0
idle: Arc<VProc>,
procs: Gutex<HashMap<Pid, Weak<VProc>>>, // allproc + pidhashtbl + zombproc
sessions: Gutex<HashMap<Pid, Weak<VSession>>>,
groups: Gutex<HashMap<Pid, Weak<VProcGroup>>>, // pgrphashtbl
last_pid: Gutex<i32>, // lastpid
@@ -846,7 +845,6 @@ impl ProcManager {
/// Events that related to a process.
#[derive(Default)]
pub struct ProcEvents {
pub process_ctor: Event<fn(&Weak<VProc>)>,
pub thread_init: Event<fn(&mut VThread)>,
pub thread_ctor: Event<fn(&Weak<VThread>)>,
}
10 changes: 0 additions & 10 deletions legacy/src/process/proc.rs
Original file line number Diff line number Diff line change
@@ -75,16 +75,6 @@ impl VProc {
uptc: AtomicPtr::new(null_mut()),
};

// Trigger process_ctor event.
let proc = Arc::new(proc);
let weak = Arc::downgrade(&proc);

for h in et.select(|s| &s.process_ctor) {
h(&weak);
}

drop(et);

Ok(proc)
}

6 changes: 6 additions & 0 deletions macros/src/bitflag.rs
Original file line number Diff line number Diff line change
@@ -117,6 +117,12 @@ pub fn transform(opts: Options, item: ItemEnum) -> syn::Result<TokenStream> {
Self(!self.0)
}
}

impl From<#impl_ident> for #ty {
fn from(value: #impl_ident) -> Self {
value.0
}
}
})
}