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

Passes memory map from VMM to kernel #1292

Merged
merged 1 commit into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
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
19 changes: 19 additions & 0 deletions config/src/env/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
pub use self::vm::*;

mod vm;

/// Implementation of `bios_smap` structure.
///
/// This basically a struct that returned from [e820](https://en.wikipedia.org/wiki/E820). All
/// non-BIOS platform (e.g. UEFI) need to populate this struct from the other sources.
#[repr(C)]
pub struct PhysMap {
pub base: u64,
pub len: u64,
pub ty: MapType,
pub attrs: u32,
}

/// Type of [PhysMap].
#[repr(u32)]
pub enum MapType {
None = 0,
Ram = 1,
}
4 changes: 4 additions & 0 deletions config/src/env/vm.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::PhysMap;
use core::num::NonZero;

/// Provides boot information when booting on a Virtual Machine.
Expand All @@ -9,6 +10,9 @@ pub struct Vm {
pub console: usize,
/// Page size on the host.
pub host_page_size: NonZero<usize>,
/// Memory map. Set [PhysMap::ty] to [MapType::None](super::MapType::None) to mark the end of
/// the list.
pub memory_map: [PhysMap; 64],
}

/// Layout of a memory for Memory-mapped I/O to communicate with VMM.
Expand Down
20 changes: 15 additions & 5 deletions gui/src/vmm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::hv::{
CpuDebug, CpuExit, CpuIo, CpuRun, CpuStates, DebugEvent, HvError, Hypervisor, Ram,
};
use crate::profile::Profile;
use config::{BootEnv, ConsoleType, Vm};
use config::{BootEnv, ConsoleType, MapType, PhysMap, Vm};
use futures::{FutureExt, select_biased};
use gdbstub::common::{Signal, Tid};
use gdbstub::target::ext::base::multithread::{
Expand Down Expand Up @@ -209,14 +209,24 @@ impl Vmm<()> {
ram.alloc_stack(NonZero::new(1024 * 1024 * 2).unwrap())
.map_err(VmmError::AllocateRamForStack)?;

// Allocate arguments.
let env = BootEnv::Vm(Vm {
// Setup boot info.
let mut env = Vm {
vmm: devices.vmm().addr(),
console: devices.console().addr(),
host_page_size,
});
memory_map: std::array::from_fn(|_| PhysMap {
base: 0,
len: 0,
ty: MapType::None,
attrs: 0,
}),
};

env.memory_map[0].base = 0;
env.memory_map[0].len = ram_size.get().try_into().unwrap();
env.memory_map[0].ty = MapType::Ram;

ram.alloc_args(env, profile.kernel_config().clone())
ram.alloc_args(BootEnv::Vm(env), profile.kernel_config().clone())
.map_err(VmmError::AllocateRamForArgs)?;

// Build RAM.
Expand Down
6 changes: 3 additions & 3 deletions kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn setup() -> ContextSetup {
// 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 procs = ProcMgr::new();
let uma = init_vm(&procs); // 161 on PS4 11.00.
let uma = init_vm(); // 161 on PS4 11.00.

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

Uma::new(vm)
}
Expand Down
19 changes: 0 additions & 19 deletions kernel/src/proc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,19 @@ 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())
}
Expand Down Expand Up @@ -72,16 +63,6 @@ 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 {}
Expand Down
37 changes: 27 additions & 10 deletions kernel/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,29 @@ 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 crate::proc::Proc;
use alloc::sync::{Arc, Weak};
use macros::bitflag;

mod object;
mod stats;

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

impl Vm {
pub fn new(procs: &Arc<ProcMgr>) -> Arc<Self> {
/// See `vm_page_startup` on the Orbis for a reference.
///
/// # Reference offsets
/// | Version | Offset |
/// |---------|--------|
/// |PS4 11.00|0x029200|
pub fn new() -> Arc<Self> {
// Initializes stats. The Orbis initialize these data in vm_pageout function but it is
// possible for data race.
// possible for data race so we do it here instead.
let pageout_page_count = 0x10; // TODO: Figure out where this value come from.
let gg = GutexGroup::new();
let stats = [
Expand All @@ -41,10 +47,11 @@ impl Vm {
},
];

Arc::new(Self {
procs: procs.clone(),
stats,
})
// Spawn page daemons. The Orbis do this in a separated sysinit but we do it here instead to
// keep it in the VM subsystem.
let pagers = Self::spawn_pagers();

Arc::new(Self { stats, pagers })
}

/// See `vm_page_alloc` on the Orbis for a reference.
Expand All @@ -69,7 +76,7 @@ impl Vm {
// 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()) {
if Arc::ptr_eq(p, &self.pagers[p.pager()].upgrade().unwrap()) {
todo!()
} else {
todo!()
Expand All @@ -78,6 +85,16 @@ impl Vm {

todo!()
}

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

/// Flags for [`Vm::alloc_page()`].
Expand Down