Skip to content

Commit 4c7f3f2

Browse files
committed
Add support for TLS templates
1 parent 76df3e5 commit 4c7f3f2

File tree

3 files changed

+50
-11
lines changed

3 files changed

+50
-11
lines changed

src/binary/load_kernel.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::binary::{level_4_entries::UsedLevel4Entries, PAGE_SIZE};
1+
use crate::{
2+
binary::{level_4_entries::UsedLevel4Entries, PAGE_SIZE},
3+
boot_info::TlsTemplate,
4+
};
25
use x86_64::{
36
align_up,
47
structures::paging::{
@@ -54,12 +57,19 @@ where
5457
Ok(loader)
5558
}
5659

57-
fn load_segments(&mut self) -> Result<(), &'static str> {
60+
fn load_segments(&mut self) -> Result<Option<TlsTemplate>, &'static str> {
61+
let mut tls_template = None;
5862
for program_header in self.elf_file.program_iter() {
5963
program::sanity_check(program_header, &self.elf_file)?;
6064
match program_header.get_type()? {
6165
Type::Load => self.inner.handle_load_segment(program_header)?,
62-
Type::Tls => self.inner.handle_tls_segment(program_header)?,
66+
Type::Tls => {
67+
if tls_template.is_none() {
68+
tls_template = Some(self.inner.handle_tls_segment(program_header)?);
69+
} else {
70+
return Err("multiple TLS segments not supported");
71+
}
72+
}
6373
Type::Null
6474
| Type::Dynamic
6575
| Type::Interp
@@ -71,7 +81,7 @@ where
7181
| Type::ProcessorSpecific(_) => {}
7282
}
7383
}
74-
Ok(())
84+
Ok(tls_template)
7585
}
7686

7787
fn entry_point(&self) -> VirtAddr {
@@ -250,19 +260,23 @@ where
250260
Ok(())
251261
}
252262

253-
fn handle_tls_segment(&mut self, segment: ProgramHeader) -> Result<(), &'static str> {
254-
todo!()
263+
fn handle_tls_segment(&mut self, segment: ProgramHeader) -> Result<TlsTemplate, &'static str> {
264+
Ok(TlsTemplate {
265+
start_addr: segment.virtual_addr(),
266+
mem_size: segment.mem_size(),
267+
file_size: segment.file_size(),
268+
})
255269
}
256270
}
257271

258272
pub fn load_kernel(
259273
bytes: &[u8],
260274
page_table: &mut impl MapperAllSizes,
261275
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
262-
) -> Result<(VirtAddr, UsedLevel4Entries), &'static str> {
276+
) -> Result<(VirtAddr, Option<TlsTemplate>, UsedLevel4Entries), &'static str> {
263277
let mut loader = Loader::new(bytes, page_table, frame_allocator)?;
264-
loader.load_segments()?;
278+
let tls_template = loader.load_segments()?;
265279
let used_entries = loader.used_level_4_entries();
266280

267-
Ok((loader.entry_point(), used_entries))
281+
Ok((loader.entry_point(), tls_template, used_entries))
268282
}

src/binary/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::binary::legacy_memory_region::{LegacyFrameAllocator, LegacyMemoryRegion};
2-
use crate::boot_info::{BootInfo, FrameBuffer, FrameBufferInfo};
2+
use crate::boot_info::{BootInfo, FrameBuffer, FrameBufferInfo, TlsTemplate};
33
use crate::memory_map::MemoryRegion;
44
use core::{
55
mem::{self, MaybeUninit},
@@ -100,7 +100,7 @@ where
100100
// Make the kernel respect the write-protection bits even when in ring 0 by default
101101
enable_write_protect_bit();
102102

103-
let (entry_point, mut used_entries) =
103+
let (entry_point, tls_template, mut used_entries) =
104104
load_kernel::load_kernel(kernel_bytes, kernel_page_table, frame_allocator)
105105
.expect("no entry point");
106106
log::info!("Entry point at: {:#x}", entry_point.as_u64());
@@ -197,6 +197,7 @@ where
197197
used_entries,
198198
physical_memory_offset,
199199
recursive_index,
200+
tls_template,
200201
}
201202
}
202203

@@ -207,6 +208,7 @@ pub struct Mappings {
207208
pub framebuffer: Option<VirtAddr>,
208209
pub physical_memory_offset: Option<VirtAddr>,
209210
pub recursive_index: Option<PageTableIndex>,
211+
pub tls_template: Option<TlsTemplate>,
210212
}
211213

212214
/// Allocates and initializes the boot info struct and the memory map
@@ -284,6 +286,7 @@ where
284286
physical_memory_offset: mappings.physical_memory_offset.map(VirtAddr::as_u64),
285287
recursive_index: mappings.recursive_index.map(Into::into),
286288
rsdp_addr: system_info.rsdp_addr.map(|addr| addr.as_u64()),
289+
tls_template: mappings.tls_template,
287290
_non_exhaustive: (),
288291
});
289292

src/boot_info.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub struct BootInfo {
88
pub physical_memory_offset: Option<u64>,
99
pub recursive_index: Option<u16>,
1010
pub rsdp_addr: Option<u64>,
11+
pub tls_template: Option<TlsTemplate>,
1112
pub(crate) _non_exhaustive: (),
1213
}
1314

@@ -50,6 +51,27 @@ pub enum PixelFormat {
5051
U8,
5152
}
5253

54+
/// Information about the thread local storage (TLS) template.
55+
///
56+
/// This template can be used to set up thread local storage for threads. For
57+
/// each thread, a new memory ___location of size `mem_size` must be initialized.
58+
/// Then the first `file_size` bytes of this template needs to be copied to the
59+
/// ___location. The additional `mem_size - file_size` bytes must be initialized with
60+
/// zero.
61+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62+
pub struct TlsTemplate {
63+
/// The virtual start address of the thread local storage template.
64+
pub start_addr: u64,
65+
/// The number of data bytes in the template.
66+
///
67+
/// Corresponds to the length of the `.tdata` section.
68+
pub file_size: u64,
69+
/// The total number of bytes that the TLS segment should have in memory.
70+
///
71+
/// Corresponds to the combined length of the `.tdata` and `.tbss` sections.
72+
pub mem_size: u64,
73+
}
74+
5375
/// Check that the _pointer_ is FFI-safe.
5476
///
5577
/// Note that the `BootInfo` struct is not FFI-safe, so it needs to be compiled by the same Rust

0 commit comments

Comments
 (0)