obkrnl/uma/
x86_64.rs

1use super::Alloc;
2use crate::vm::{PageFlags, Vm};
3use core::sync::atomic::{AtomicUsize, Ordering};
4use krt::phys_vaddr;
5
6/// See `uma_small_alloc` on the Orbis for a reference.
7///
8/// # Reference offsets
9/// | Version | Offset |
10/// |---------|--------|
11/// |PS4 11.00|0x22FD70|
12pub fn small_alloc(vm: &Vm, flags: Alloc) -> *mut u8 {
13    // TODO: Figure out the name of this static variable. Also the Orbis does not use atomic
14    // operation here.
15    static UNK: AtomicUsize = AtomicUsize::new(0);
16
17    // TODO: Refactor this for readability.
18    let req = ((((u32::from(flags) & 0x100) >> 2) - (u32::from((u32::from(flags) & 0x401) == 1))
19        + 0x22)
20        | 0x100)
21        .into();
22    let page = loop {
23        match vm.alloc_page(None, UNK.fetch_add(1, Ordering::Relaxed), req) {
24            Some(v) => break v,
25            None => todo!(),
26        }
27    };
28
29    // TODO: The Orbis set unknown field on vm_page here.
30    let ps = page.state.lock();
31
32    if flags.has_any(Alloc::Zero) && !ps.flags.has_any(PageFlags::Zero) {
33        // SAFETY: The page just allocated so we have exclusive access.
34        unsafe { page.fill_with_zeros() };
35    }
36
37    (phys_vaddr() + page.addr) as *mut u8
38}