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