From 27cb81b295be77ffc24bc096fae02baf63bba653 Mon Sep 17 00:00:00 2001 From: Ruihan Li Date: Tue, 13 Jan 2026 23:49:07 +0800 Subject: [PATCH] Clean up the `init_stack` module --- kernel/src/context.rs | 8 +- .../process/process_vm/init_stack/aux_vec.rs | 19 +-- .../src/process/process_vm/init_stack/mod.rs | 120 +++++++----------- 3 files changed, 52 insertions(+), 95 deletions(-) diff --git a/kernel/src/context.rs b/kernel/src/context.rs index 76940bf9d..134a4c32f 100644 --- a/kernel/src/context.rs +++ b/kernel/src/context.rs @@ -6,7 +6,7 @@ use core::cell::Ref; use inherit_methods_macro::inherit_methods; use ostd::{ - mm::{Fallible, MAX_USERSPACE_VADDR, PodAtomic, VmIo, VmReader, VmWriter}, + mm::{Fallible, PodAtomic, VmIo, VmReader, VmWriter}, task::Task, }; @@ -17,7 +17,7 @@ use crate::{ posix_thread::{PosixThread, ThreadLocal}, }, thread::Thread, - vm::vmar::{VMAR_LOWEST_ADDR, Vmar}, + vm::vmar::{VMAR_CAP_ADDR, VMAR_LOWEST_ADDR, Vmar}, }; /// The context that can be accessed from the current POSIX thread. @@ -205,10 +205,10 @@ impl<'a> CurrentUserSpace<'a> { check_vaddr_lowerbound(vaddr)?; } - // Adjust `max_len` to ensure `vaddr + max_len` does not exceed `MAX_USERSPACE_VADDR`. + // Adjust `max_len` to ensure `vaddr + max_len` does not exceed `VMAR_CAP_ADDR`. // If `vaddr` is outside user address space, `userspace_max_len` will be set to zero and // further call to `self.reader` will return `EFAULT`. - let userspace_max_len = MAX_USERSPACE_VADDR.saturating_sub(vaddr).min(max_len); + let userspace_max_len = VMAR_CAP_ADDR.saturating_sub(vaddr).min(max_len); let mut user_reader = self.reader(vaddr, userspace_max_len)?; user_reader.read_cstring_until_nul(userspace_max_len)? diff --git a/kernel/src/process/process_vm/init_stack/aux_vec.rs b/kernel/src/process/process_vm/init_stack/aux_vec.rs index bec2f04d2..622a4a842 100644 --- a/kernel/src/process/process_vm/init_stack/aux_vec.rs +++ b/kernel/src/process/process_vm/init_stack/aux_vec.rs @@ -1,7 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -#![expect(dead_code)] - use crate::prelude::*; /// Auxiliary Vector. @@ -15,6 +13,7 @@ use crate::prelude::*; /// > is a table of key-value pairs, where the keys are from the set of ‘AT_’ /// > values in elf.h. #[expect(non_camel_case_types)] +#[expect(dead_code)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(u8)] pub enum AuxKey { @@ -50,12 +49,6 @@ pub enum AuxKey { AT_SYSINFO_EHDR = 33, /* the start address of the page containing the VDSO */ } -impl AuxKey { - pub fn as_u64(&self) -> u64 { - *self as u64 - } -} - #[derive(Clone, Default, Debug)] pub struct AuxVec { table: BTreeMap, @@ -67,9 +60,7 @@ impl AuxVec { table: BTreeMap::new(), } } -} -impl AuxVec { pub fn set(&mut self, key: AuxKey, val: u64) -> Result<()> { if key == AuxKey::AT_NULL || key == AuxKey::AT_IGNORE { return_errno_with_message!(Errno::EINVAL, "Illegal key"); @@ -81,14 +72,6 @@ impl AuxVec { Ok(()) } - pub fn get(&self, key: AuxKey) -> Option { - self.table.get(&key).copied() - } - - pub fn del(&mut self, key: AuxKey) -> Option { - self.table.remove(&key) - } - pub fn table(&self) -> &BTreeMap { &self.table } diff --git a/kernel/src/process/process_vm/init_stack/mod.rs b/kernel/src/process/process_vm/init_stack/mod.rs index fc1addfa8..0bf9b7ca3 100644 --- a/kernel/src/process/process_vm/init_stack/mod.rs +++ b/kernel/src/process/process_vm/init_stack/mod.rs @@ -1,16 +1,15 @@ // SPDX-License-Identifier: MPL-2.0 -#![expect(dead_code)] - //! The init stack for the process. -//! The init stack is used to store the `argv` and `envp` and auxiliary vectors. +//! +//! The init stack is used to store `argv`, `envp`, and auxiliary vectors. //! We can read `argv` and `envp` of a process from the init stack. -//! Usually, the lowest address of init stack is -//! the highest address of the user stack of the first thread. +//! Usually, the lowest address of the init stack is +//! the highest address of the user stack of the main thread. //! //! However, the init stack will be mapped to user space -//! and the user process can write the content of init stack, -//! so the content reading from init stack may not be the same as the process init status. +//! and the user process can write the content of the init stack, +//! so the content reading from the init stack may not be the same as the initial one. //! use core::{ @@ -18,7 +17,7 @@ use core::{ sync::atomic::{AtomicUsize, Ordering}, }; -use ostd::mm::{MAX_USERSPACE_VADDR, VmIo}; +use ostd::mm::VmIo; use self::aux_vec::{AuxKey, AuxVec}; use crate::{ @@ -26,7 +25,7 @@ use crate::{ util::random::getrandom, vm::{ perms::VmPerms, - vmar::Vmar, + vmar::{VMAR_CAP_ADDR, Vmar}, vmo::{Vmo, VmoOptions}, }, }; @@ -97,15 +96,16 @@ pub const MAX_LEN_STRING_ARG: usize = PAGE_SIZE * 32; /// The initial portion of the main stack of a process. pub struct InitStack { - /// The initial highest address. - /// The stack grows down from this address + /// The top address of the init stack. + /// + /// The stack grows down from this address. initial_top: Vaddr, - /// The max allowed stack size + /// The maximum size of the stack. max_size: usize, /// The current stack pointer. - /// Before initialized, `pos` points to the `initial_top`, - /// After initialized, `pos` points to the user stack pointer(rsp) - /// of the process. + /// + /// Before initialization, `pos` points to `initial_top`. + /// After initialization, `pos` points to the top of the process stack. pos: AtomicUsize, argv_range: SpinLock>, envp_range: SpinLock>, @@ -126,7 +126,7 @@ impl Clone for InitStack { impl InitStack { pub fn new() -> Self { let nr_pages_padding = { - // We do not want the stack top too close to MAX_USERSPACE_VADDR. + // We do not want the stack top too close to `VMAR_CAP_ADDR`. // So we add this fixed padding. Any small value greater than zero will do. const NR_FIXED_PADDING_PAGES: usize = 7; @@ -138,7 +138,7 @@ impl InitStack { nr_random_padding_pages as usize + NR_FIXED_PADDING_PAGES }; - let initial_top = MAX_USERSPACE_VADDR - PAGE_SIZE * nr_pages_padding; + let initial_top = VMAR_CAP_ADDR - PAGE_SIZE * nr_pages_padding; let max_size = INIT_STACK_SIZE; Self { @@ -150,14 +150,13 @@ impl InitStack { } } - /// Returns the user stack top(highest address), used to setup rsp. + /// Returns the top address of the user stack. /// /// This method should only be called after the stack is initialized. pub fn user_stack_top(&self) -> Vaddr { - let stack_top = self.pos(); debug_assert!(self.is_initialized()); - stack_top + self.pos() } /// Maps the VMO of the init stack and constructs a writer to initialize its content. @@ -201,13 +200,13 @@ impl InitStack { } /// Constructs a reader to parse the content of an `InitStack`. - /// The `InitStack` should only be read after initialized + /// + /// This method should only be called after the stack is initialized. pub(super) fn reader<'a>(&self, vmar: &'a Vmar) -> InitStackReader<'a> { debug_assert!(self.is_initialized()); + InitStackReader { - base: self.pos(), vmar, - map_addr: self.initial_top - self.max_size, argv_range: self.argv_range.lock().clone(), envp_range: self.envp_range.lock().clone(), } @@ -242,22 +241,20 @@ impl InitStackWriter<'_> { /// /// Returns the range of argv and envp in the init stack. fn write(mut self) -> Result<(Range, Range)> { - // FIXME: Some OSes may put the first page of executable file here - // for interpreting elf headers. + // FIXME: Some OSes may put the first page of the executable file here + // for interpreting ELF headers. - let argc = self.argv.len() as u64; - - // Write envp string + // Write envp strings. let envp_end = self.pos(); let envp_pointers = self.write_envp_strings()?; let envp_start = self.pos(); - // Write argv string + // Write argv strings. let argv_end = self.pos(); let argv_pointers = self.write_argv_strings()?; let argv_start = self.pos(); - // Generate random values for auxvec + // Generate random values for the auxiliary vector. let random_value_pointer = { let random_value = generate_random_for_aux_vec(); self.write_bytes(&random_value)? @@ -269,10 +266,11 @@ impl InitStackWriter<'_> { self.write_envp_pointers(envp_pointers)?; self.write_argv_pointers(argv_pointers)?; - // write argc - self.write_u64(argc)?; + // Write argc. + let argc = self.argv.len(); + self.write_u64(argc as u64)?; - // Ensure stack top is 16-bytes aligned + // Ensure the stack top is 16-byte aligned. debug_assert_eq!(self.pos() & !0xf, self.pos()); Ok((argv_start..argv_end, envp_start..envp_end)) @@ -298,11 +296,12 @@ impl InitStackWriter<'_> { Ok(argv_pointers) } - /// Libc ABI requires 16-byte alignment of the stack entrypoint. - /// Current position of the stack is 8-byte aligned already, insert 8 byte - /// to meet the requirement if necessary. + /// Ensures that the top address of the user stack is 16-byte aligned. + /// + /// The 16-byte alignment is required by x86-64 System V ABI. + /// To meet that requirement, this method may write some extra 8-byte `u64`s. fn adjust_stack_alignment(&self, envp_pointers: &[u64], argv_pointers: &[u64]) -> Result<()> { - // Ensure 8-byte alignment + // Ensure 8-byte alignment. self.write_u64(0)?; let auxvec_size = (self.auxvec.table().len() + 1) * (size_of::() * 2); let envp_pointers_size = (envp_pointers.len() + 1) * size_of::(); @@ -316,10 +315,10 @@ impl InitStackWriter<'_> { } fn write_aux_vec(&self) -> Result<()> { - // Write NULL auxiliary + // Write a NULL auxiliary entry. self.write_u64(0)?; self.write_u64(AuxKey::AT_NULL as u64)?; - // Write Auxiliary vectors + // Write the auxiliary vector. let aux_vec: Vec<_> = self .auxvec .table() @@ -334,9 +333,9 @@ impl InitStackWriter<'_> { } fn write_envp_pointers(&self, mut envp_pointers: Vec) -> Result<()> { - // write NULL pointer + // Write a NULL pointer. self.write_u64(0)?; - // write envp pointers + // Write envp pointers. envp_pointers.reverse(); for envp_pointer in envp_pointers { self.write_u64(envp_pointer)?; @@ -345,9 +344,9 @@ impl InitStackWriter<'_> { } fn write_argv_pointers(&self, mut argv_pointers: Vec) -> Result<()> { - // write 0 + // Write a NULL pointer. self.write_u64(0)?; - // write argv pointers + // Write argv pointers. argv_pointers.reverse(); for argv_pointer in argv_pointers { self.write_u64(argv_pointer)?; @@ -355,16 +354,16 @@ impl InitStackWriter<'_> { Ok(()) } - /// Writes u64 to the stack. - /// Returns the writing address + /// Writes a `u64` to the stack. + /// Returns the writing address. fn write_u64(&self, val: u64) -> Result { let new_pos = self.reserve_pos(size_of::(), align_of::())?; self.vmo.write_val(new_pos - self.map_addr, &val)?; Ok(new_pos as u64) } - /// Writes a CString including the ending null byte to the stack. - /// Returns the writing address + /// Writes a `CString` including the nul byte to the stack. + /// Returns the writing address. fn write_cstring(&self, val: &CString) -> Result { let bytes = val.as_bytes_with_nul(); self.write_bytes(bytes) @@ -386,7 +385,7 @@ impl InitStackWriter<'_> { self.pos.store(new_pos, Ordering::Relaxed); return Ok(new_pos); } - return_errno_with_message!(Errno::E2BIG, "Init stack overflow"); + return_errno_with_message!(Errno::E2BIG, "the init stack overflows"); } fn pos(&self) -> Vaddr { @@ -402,32 +401,12 @@ fn generate_random_for_aux_vec() -> [u8; 16] { /// A reader to parse the content of an `InitStack`. pub struct InitStackReader<'a> { - base: Vaddr, vmar: &'a Vmar, - /// The mapping address of the `InitStack`. - map_addr: usize, argv_range: Range, envp_range: Range, } impl InitStackReader<'_> { - /// Reads argc from the process init stack. - pub fn argc(&self) -> Result { - let mut buffer = [0u8; 8]; - - self.vmar.read_remote( - self.init_stack_bottom(), - &mut VmWriter::from(&mut buffer[..]).to_fallible(), - )?; - - let argc = u64::from_ne_bytes(buffer); - if argc > MAX_NR_STRING_ARGS as u64 { - return_errno_with_message!(Errno::EINVAL, "argc is corrupted"); - } - - Ok(argc) - } - /// Reads argv at the `offset` from the process init stack. pub fn argv(&self, offset: usize, writer: &mut VmWriter) -> Result { if offset >= self.argv_range.end - self.argv_range.start { @@ -453,9 +432,4 @@ impl InitStackReader<'_> { Ok(bytes_read) } - - /// Returns the bottom address of the init stack (lowest address). - pub const fn init_stack_bottom(&self) -> Vaddr { - self.base - } }