From 9e8cd0bf0736251614a23275048762877c3ad471 Mon Sep 17 00:00:00 2001 From: Peter Limkilde Svendsen <peter.limkilde@gmail.com> Date: Wed, 24 Mar 2021 00:02:39 +0100 Subject: [PATCH] Centralize page size info in platform abstraction --- src/header/unistd/sysconf.rs | 8 ++++++-- src/ld_so/mod.rs | 13 ++++++++----- src/ld_so/tcb.rs | 24 +++++++++++++++--------- src/platform/linux/mod.rs | 4 ++++ src/platform/pal/mod.rs | 5 +++++ src/platform/redox/mod.rs | 4 ++++ 6 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/header/unistd/sysconf.rs b/src/header/unistd/sysconf.rs index 103ab07d..423d4d49 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 e4e62282..9ee7ea53 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 0493f303..a1058c94 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 7e996a0f..2190237d 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 f7984dac..dd953b85 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 580fd47f..c651ec34 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 } -- GitLab