proc: better TLS handling
This commit is contained in:
parent
ce2de4bf9d
commit
2d9cc793e0
@ -13,6 +13,7 @@ use libk_mm::{
|
||||
pointer::{PhysicalRef, PhysicalRefMut},
|
||||
process::{ProcessAddressSpace, VirtualRangeBacking},
|
||||
table::MapAttributes,
|
||||
PageBox,
|
||||
};
|
||||
use libk_util::io::{Read, Seek};
|
||||
use yggdrasil_abi::{error::Error, io::SeekFrom, path::PathBuf};
|
||||
@ -20,6 +21,7 @@ use yggdrasil_abi::{error::Error, io::SeekFrom, path::PathBuf};
|
||||
use crate::{
|
||||
random,
|
||||
task::{
|
||||
mem::ForeignPointer,
|
||||
process::ProcessImage,
|
||||
types::{ProcessTlsInfo, ProcessTlsLayout},
|
||||
},
|
||||
@ -233,34 +235,52 @@ pub fn clone_tls(space: &ProcessAddressSpace, image: &ProcessImage) -> Result<us
|
||||
return Ok(0);
|
||||
};
|
||||
|
||||
assert_ne!(tls.master_copy_base, 0);
|
||||
assert_ne!(tls.layout.mem_size, 0);
|
||||
assert_ne!(tls.layout.full_size, 0);
|
||||
let aligned_size = (tls.layout.full_size + 0xFFF) & !0xFFF;
|
||||
|
||||
let address = space.allocate(
|
||||
None,
|
||||
0x1000,
|
||||
aligned_size,
|
||||
VirtualRangeBacking::anonymous(),
|
||||
MapAttributes::USER_READ | MapAttributes::USER_WRITE | MapAttributes::NON_GLOBAL,
|
||||
MapAttributes::USER_WRITE | MapAttributes::USER_READ | MapAttributes::NON_GLOBAL,
|
||||
)?;
|
||||
|
||||
let src_phys = space.translate(tls.master_copy_base)?;
|
||||
let dst_phys = space.translate(address)?;
|
||||
|
||||
// Copy data
|
||||
unsafe {
|
||||
let src =
|
||||
PhysicalRef::<u8>::map_slice(src_phys.add(tls.layout.data_offset), tls.layout.mem_size);
|
||||
let mut dst =
|
||||
PhysicalRefMut::map_slice(dst_phys.add(tls.layout.data_offset), tls.layout.mem_size);
|
||||
|
||||
dst.copy_from_slice(&src);
|
||||
// Copy master image data
|
||||
if tls.layout.data_size > 0 {
|
||||
let master_copy = tls.master_copy.as_ref().unwrap();
|
||||
load_bytes(
|
||||
space,
|
||||
address + tls.layout.data_offset,
|
||||
tls.layout.data_size,
|
||||
|off, mut data| {
|
||||
let len = data.len();
|
||||
data.copy_from_slice(&master_copy[off..off + len]);
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
// Setup self-pointer
|
||||
unsafe {
|
||||
let mut dst = PhysicalRefMut::<usize>::map(dst_phys.add(tls.layout.ptr_offset));
|
||||
// Zero zeroed data
|
||||
if tls.layout.mem_size > tls.layout.data_size {
|
||||
load_bytes(
|
||||
space,
|
||||
address + tls.layout.data_offset + tls.layout.data_size,
|
||||
tls.layout.mem_size - tls.layout.data_size,
|
||||
|_, mut data| {
|
||||
data.fill(0);
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
*dst = address + tls.layout.ptr_offset;
|
||||
// Zero slots and setup self-pointer
|
||||
unsafe {
|
||||
let slots: *mut usize = core::ptr::without_provenance_mut(address + tls.layout.slot_offset);
|
||||
slots.try_write_foreign_volatile(space, 0)?;
|
||||
slots.add(1).try_write_foreign_volatile(space, 0)?;
|
||||
let self_ptr: *mut usize =
|
||||
core::ptr::without_provenance_mut(address + tls.layout.ptr_offset);
|
||||
self_ptr.try_write_foreign_volatile(space, address + tls.layout.ptr_offset)?;
|
||||
}
|
||||
|
||||
Ok(address + tls.layout.ptr_offset)
|
||||
@ -401,43 +421,20 @@ fn handle_tls<F: Read + Seek>(
|
||||
tls_segment.p_filesz as _,
|
||||
tls_segment.p_memsz as _,
|
||||
);
|
||||
let data_offset = layout.data_offset;
|
||||
let data_size = layout.data_size;
|
||||
let mem_size = layout.mem_size;
|
||||
let aligned_size = (layout.full_size + 0xFFF) & !0xFFF;
|
||||
|
||||
let attrs =
|
||||
MapAttributes::USER_WRITE | MapAttributes::USER_READ | MapAttributes::NON_GLOBAL;
|
||||
let master_copy_base =
|
||||
space.allocate(None, aligned_size, VirtualRangeBacking::anonymous(), attrs)?;
|
||||
assert!(layout.mem_size <= layout.full_size);
|
||||
|
||||
if data_size > 0 {
|
||||
load_bytes(
|
||||
space,
|
||||
master_copy_base + data_offset,
|
||||
data_size,
|
||||
|off, mut dst| {
|
||||
file.file
|
||||
.seek(SeekFrom::Start(tls_segment.p_offset + off as u64))?;
|
||||
file.file.read_exact(dst.deref_mut())
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
if mem_size > data_size {
|
||||
load_bytes(
|
||||
space,
|
||||
master_copy_base + data_offset + data_size,
|
||||
mem_size - data_size,
|
||||
|_, mut dst| {
|
||||
dst.fill(0);
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
}
|
||||
let master_copy = if layout.data_size > 0 {
|
||||
let mut data = PageBox::new_slice(0, layout.data_size)?;
|
||||
file.file.seek(SeekFrom::Start(tls_segment.p_offset))?;
|
||||
file.file.read_exact(&mut data)?;
|
||||
Some(Arc::new(data))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Some(ProcessTlsInfo {
|
||||
master_copy_base,
|
||||
master_copy,
|
||||
layout,
|
||||
}))
|
||||
} else {
|
||||
|
@ -1,6 +1,8 @@
|
||||
use core::{alloc::Layout, mem::size_of};
|
||||
|
||||
use libk_mm::{address::Virtualize, process::ProcessAddressSpace};
|
||||
use libk_mm::{
|
||||
address::Virtualize, pointer::PhysicalRef, process::ProcessAddressSpace, table::EntryLevelExt,
|
||||
};
|
||||
use yggdrasil_abi::error::Error;
|
||||
|
||||
// XXX
|
||||
|
@ -1,9 +1,12 @@
|
||||
use alloc::sync::Arc;
|
||||
use core::{
|
||||
fmt,
|
||||
range::Range,
|
||||
sync::atomic::{AtomicU32, AtomicU64, Ordering},
|
||||
};
|
||||
|
||||
use atomic_enum::atomic_enum;
|
||||
use libk_mm::PageBox;
|
||||
use yggdrasil_abi::process::ProcessId;
|
||||
|
||||
pub trait AllocateProcessId {
|
||||
@ -52,8 +55,8 @@ pub enum ThreadId {
|
||||
/// Describes Thread-Local Storage of a process
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ProcessTlsInfo {
|
||||
/// Location of the TLS master copy within the process's memory
|
||||
pub master_copy_base: usize,
|
||||
/// Master copy of the TLS
|
||||
pub master_copy: Option<Arc<PageBox<[u8]>>>,
|
||||
/// Layout of the TLS
|
||||
pub layout: ProcessTlsLayout,
|
||||
}
|
||||
@ -61,18 +64,12 @@ pub struct ProcessTlsInfo {
|
||||
/// Describes TLS layout for a program image
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ProcessTlsLayout {
|
||||
/// Data offset from the TLS base
|
||||
pub data_offset: usize,
|
||||
/// struct uthread offset from the TLS base
|
||||
pub uthread_offset: usize,
|
||||
/// Pointer offset from the TLS base. The pointer is passed to the userspace
|
||||
pub ptr_offset: usize,
|
||||
|
||||
/// Data size of the TLS segment
|
||||
pub data_offset: usize,
|
||||
pub data_size: usize,
|
||||
/// Memory size of the TLS segment (mem_size >= data_size)
|
||||
pub mem_size: usize,
|
||||
|
||||
pub slot_offset: usize,
|
||||
/// Overall allocation size of the TLS data
|
||||
pub full_size: usize,
|
||||
}
|
||||
@ -170,8 +167,8 @@ impl ProcessTlsLayout {
|
||||
|
||||
Self {
|
||||
data_offset: tls_block0_offset + back_size,
|
||||
uthread_offset: back_size,
|
||||
ptr_offset: back_size,
|
||||
slot_offset: 0,
|
||||
|
||||
data_size,
|
||||
mem_size,
|
||||
@ -200,8 +197,8 @@ impl ProcessTlsLayout {
|
||||
|
||||
Self {
|
||||
data_offset: 0,
|
||||
uthread_offset: back_size,
|
||||
ptr_offset: back_size,
|
||||
slot_offset: back_size + 2 * size_of::<usize>(),
|
||||
|
||||
data_size,
|
||||
mem_size,
|
||||
@ -222,8 +219,8 @@ impl ProcessTlsLayout {
|
||||
|
||||
Self {
|
||||
data_offset: 0,
|
||||
uthread_offset: back_size,
|
||||
ptr_offset: back_size,
|
||||
slot_offset: back_size + 2 * size_of::<usize>(),
|
||||
|
||||
data_size,
|
||||
mem_size,
|
||||
|
Loading…
x
Reference in New Issue
Block a user