From f028d951e046afd8da80a7670a566ce0ab0b1d41 Mon Sep 17 00:00:00 2001 From: Putta Khunchalee Date: Mon, 24 Feb 2025 22:32:49 +0700 Subject: [PATCH] Passes memory map from VMM to kernel --- config/src/env/mod.rs | 19 +++++++++++++++++++ config/src/env/vm.rs | 4 ++++ gui/src/vmm/mod.rs | 20 +++++++++++++++----- kernel/src/main.rs | 6 +++--- kernel/src/proc/mod.rs | 19 ------------------- kernel/src/vm/mod.rs | 37 +++++++++++++++++++++++++++---------- 6 files changed, 68 insertions(+), 37 deletions(-) diff --git a/config/src/env/mod.rs b/config/src/env/mod.rs index 3d442ecf3..1ff4cb4a6 100644 --- a/config/src/env/mod.rs +++ b/config/src/env/mod.rs @@ -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, +} diff --git a/config/src/env/vm.rs b/config/src/env/vm.rs index 86664f89a..e7dfe0c95 100644 --- a/config/src/env/vm.rs +++ b/config/src/env/vm.rs @@ -1,3 +1,4 @@ +use super::PhysMap; use core::num::NonZero; /// Provides boot information when booting on a Virtual Machine. @@ -9,6 +10,9 @@ pub struct Vm { pub console: usize, /// Page size on the host. pub host_page_size: NonZero, + /// 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. diff --git a/gui/src/vmm/mod.rs b/gui/src/vmm/mod.rs index 4cff25769..819ca8384 100644 --- a/gui/src/vmm/mod.rs +++ b/gui/src/vmm/mod.rs @@ -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::{ @@ -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. diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 36d990888..143a23fd1 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -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 } } @@ -85,8 +85,8 @@ fn run() -> ! { /// | Version | Offset | /// |---------|--------| /// |PS4 11.00|0x39A390| -fn init_vm(procs: &Arc) -> Arc { - let vm = Vm::new(procs); +fn init_vm() -> Arc { + let vm = Vm::new(); Uma::new(vm) } diff --git a/kernel/src/proc/mod.rs b/kernel/src/proc/mod.rs index c3276497a..428e4124c 100644 --- a/kernel/src/proc/mod.rs +++ b/kernel/src/proc/mod.rs @@ -22,28 +22,19 @@ mod thread; /// Manage all processes in the system. pub struct ProcMgr { procs: Mutex>>, // allproc + pidhashtbl + zombproc - pagers: [Weak; 2], // pageproc events: Arc>, } impl ProcMgr { pub fn new() -> Arc { - 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 { - &self.pagers[i] - } - pub fn list(&self) -> MappedMutex> + '_> { MutexGuard::map(self.procs.lock(), |procs| procs.values()) } @@ -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; 2] { - todo!() - } } impl Subsystem for ProcMgr {} diff --git a/kernel/src/vm/mod.rs b/kernel/src/vm/mod.rs index 769f2f962..adb24c6bc 100644 --- a/kernel/src/vm/mod.rs +++ b/kernel/src/vm/mod.rs @@ -3,8 +3,8 @@ 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; @@ -12,14 +12,20 @@ mod stats; /// Implementation of Virtual Memory system. pub struct Vm { - procs: Arc, stats: [VmStats; 3], + pagers: [Weak; 2], // pageproc } impl Vm { - pub fn new(procs: &Arc) -> Arc { + /// See `vm_page_startup` on the Orbis for a reference. + /// + /// # Reference offsets + /// | Version | Offset | + /// |---------|--------| + /// |PS4 11.00|0x029200| + pub fn new() -> Arc { // 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 = [ @@ -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. @@ -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!() @@ -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; 2] { + todo!() + } } /// Flags for [`Vm::alloc_page()`].