diff --git a/src/header/unistd/sysconf.rs b/src/header/unistd/sysconf.rs index 103ab07db42df2026481db82254d1605ebab8b33..423d4d49dd4a27a7c71eb41e0601bb3fc08d4a56 100644 --- a/src/header/unistd/sysconf.rs +++ b/src/header/unistd/sysconf.rs @@ -1,6 +1,8 @@ +use core::convert::TryInto; + use crate::{ header::errno, - platform::{self, types::*}, + platform::{self, types::*, Pal, Sys}, }; // POSIX.1 { @@ -39,7 +41,9 @@ pub extern "C" fn sysconf(name: c_int) -> c_long { _SC_STREAM_MAX => 16, _SC_TZNAME_MAX => -1, _SC_VERSION => 200809, - _SC_PAGESIZE => 4096, + _SC_PAGESIZE => Sys::getpagesize() + .try_into() + .expect("page size not representable as type `long`"), _SC_RE_DUP_MAX => 32767, _SC_GETPW_R_SIZE_MAX => -1, _SC_LOGIN_NAME_MAX => 256, diff --git a/src/ld_so/mod.rs b/src/ld_so/mod.rs index e4e62282b77f16f91ae77fdf0fd4d0d283accd82..9ee7ea5322868ec06fddd2914d4cd7989373ed25 100644 --- a/src/ld_so/mod.rs +++ b/src/ld_so/mod.rs @@ -2,9 +2,11 @@ use core::{mem, ptr}; use goblin::elf::program_header::{self, program_header32, program_header64, ProgramHeader}; use self::tcb::{Master, Tcb}; -use crate::{header::sys_auxv::AT_NULL, start::Stack}; - -pub const PAGE_SIZE: usize = 4096; +use crate::{ + header::sys_auxv::AT_NULL, + platform::{Pal, Sys}, + start::Stack, +}; #[cfg(target_os = "redox")] pub const PATH_SEP: char = ';'; @@ -64,9 +66,10 @@ pub fn static_init(sp: &'static Stack) { _ => panic!("unknown AT_PHENT size {}", phent), }; - let voff = ph.p_vaddr as usize % PAGE_SIZE; + let page_size = Sys::getpagesize(); + let voff = ph.p_vaddr as usize % page_size; let vaddr = ph.p_vaddr as usize - voff; - let vsize = ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; + let vsize = ((ph.p_memsz as usize + voff + page_size - 1) / page_size) * page_size; match ph.p_type { program_header::PT_TLS => { diff --git a/src/ld_so/tcb.rs b/src/ld_so/tcb.rs index 0493f303e622e449da865d37fa7424c39c76e404..a1058c941f2327396ebecbdb79bd385506b08452 100644 --- a/src/ld_so/tcb.rs +++ b/src/ld_so/tcb.rs @@ -2,9 +2,12 @@ use alloc::vec::Vec; use core::{mem, ptr, slice}; use goblin::error::{Error, Result}; -use crate::{header::sys_mman, ld_so::linker::Linker, sync::mutex::Mutex}; - -use super::PAGE_SIZE; +use crate::{ + header::sys_mman, + ld_so::linker::Linker, + platform::{Pal, Sys}, + sync::mutex::Mutex, +}; #[repr(C)] #[derive(Debug)] @@ -29,11 +32,11 @@ impl Master { pub struct Tcb { /// Pointer to the end of static TLS. Must be the first member pub tls_end: *mut u8, - /// Size of the memory allocated for the static TLS in bytes (multiple of PAGE_SIZE) + /// Size of the memory allocated for the static TLS in bytes (multiple of page size) pub tls_len: usize, /// Pointer to this structure pub tcb_ptr: *mut Tcb, - /// Size of the memory allocated for this structure in bytes (should be PAGE_SIZE) + /// Size of the memory allocated for this structure in bytes (should be same as page size) pub tcb_len: usize, /// Pointer to a list of initial TLS data pub masters_ptr: *mut Master, @@ -50,7 +53,8 @@ pub struct Tcb { impl Tcb { /// Create a new TCB pub unsafe fn new(size: usize) -> Result<&'static mut Self> { - let (tls, tcb_page) = Self::os_new(round_up(size, PAGE_SIZE))?; + let page_size = Sys::getpagesize(); + let (tls, tcb_page) = Self::os_new(round_up(size, page_size))?; let tcb_ptr = tcb_page.as_mut_ptr() as *mut Self; trace!("New TCB: {:p}", tcb_ptr); @@ -185,7 +189,8 @@ impl Tcb { /// OS specific code to create a new TLS and TCB - Linux #[cfg(target_os = "linux")] unsafe fn os_new(size: usize) -> Result<(&'static mut [u8], &'static mut [u8])> { - let tls_tcb = Self::map(size + PAGE_SIZE)?; + let page_size = Sys::getpagesize(); + let tls_tcb = Self::map(size + page_size)?; Ok(tls_tcb.split_at_mut(size)) } @@ -195,12 +200,13 @@ impl Tcb { use crate::header::unistd; //TODO: better method of finding fs offset let pid = unistd::getpid(); - let tcb_addr = 0xB000_0000 + pid as usize * PAGE_SIZE; + let page_size = Sys::getpagesize(); + let tcb_addr = 0xB000_0000 + pid as usize * page_size; let tls = Self::map(size)?; Ok(( tls, //TODO: Consider allocating TCB as part of TLS - slice::from_raw_parts_mut(tcb_addr as *mut u8, PAGE_SIZE), + slice::from_raw_parts_mut(tcb_addr as *mut u8, page_size), )) } diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 7e996a0fc6b7e9956b658b9c1abf7448caa46224..2190237d0e4d307cc4903f3faa6877f0aa7e3c11 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -242,6 +242,10 @@ impl Pal for Sys { e(unsafe { syscall!(GETGID) }) as gid_t } + fn getpagesize() -> usize { + 4096 + } + fn getpgid(pid: pid_t) -> pid_t { e(unsafe { syscall!(GETPGID, pid) }) as pid_t } diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index f7984dac6917d7aaf81ac76dc6aceda2460deed6..dd953b85d054a309f4bc7eaed82cf340eaf3317f 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -85,6 +85,11 @@ pub trait Pal { fn getgid() -> gid_t; + /* Note that this is distinct from the legacy POSIX function + * getpagesize(), which returns a c_int. On some Linux platforms, + * page size may be determined through a syscall ("getpagesize"). */ + fn getpagesize() -> usize; + fn getpgid(pid: pid_t) -> pid_t; fn getpid() -> pid_t; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 580fd47fdd62384ffb13f7b8a0c27da48ec145a9..c651ec34da9b1fffa42a3f7ee234932ee9f15283 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -604,6 +604,10 @@ impl Pal for Sys { e(syscall::getgid()) as gid_t } + fn getpagesize() -> usize { + 4096 + } + fn getpgid(pid: pid_t) -> pid_t { e(syscall::getpgid(pid as usize)) as pid_t }